Commit 6f19f271 authored by Lionel Seinturier's avatar Lionel Seinturier

Support component implementations with unannotated POJOs.

parent a384d387
......@@ -74,6 +74,7 @@ In addition the examples/advanced directory contains some advanced samples. See
the README.txt in the corresponding directories to obtain more information about
these samples.
- helloworld-bin: binary components (compiled classes) with Tinfi
- helloworld-pojo: the Hello World example with POJO component implementations
- helloworld-with-intent: the Hello World example with policy sets
......@@ -86,14 +87,8 @@ mvn install
4. Running the sample applications
----------------------------------
After having installed Tinfi (see Section 3), to compile and run the tests which
come with the forge sample application, type:
cd examples/forge
mvn test
To compile and run the helloworld sample application, type:
cd examples/helloworld
mvn compile
mvn -Ptinfi:run
......@@ -184,4 +179,4 @@ To run the conformance tests, type:
For any question, please contact: Lionel.Seinturier@univ-lille1.fr
Date of creation of this file: June 24, 2007.
Last modified: November 28, 2008.
Last modified: January 25, 2009.
......@@ -2,6 +2,7 @@ Tinfi 0.4.4
-----------
* move to org.ow2.frascati for artifacts and Java packages
* support SCA annotations on private fields (feature suggested by Nicolas P.)
* support unannotated POJO component implementations
Tinfi 0.4.3
......
mixins/
* support unannotated Java Bean content classes
runtime/
* add listFcHandlers and removeFcHandlers methods in SCABasicIntentController
* provide a runtime-generic module which would be able to instanciate components
......
To compile and run the example:
mvn -Ptinfi:run
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.ow2.frascati.tinfi</groupId>
<artifactId>frascati-tinfi-parent</artifactId>
<version>0.4.4-SNAPSHOT</version>
</parent>
<groupId>org.ow2.frascati.tinfi.examples</groupId>
<artifactId>frascati-tinfi-helloworld-pojo</artifactId>
<packaging>jar</packaging>
<name>Tinfi HelloWorld example with POJO component implementations</name>
<!-- ================================================== -->
<!-- Properties used for lauching the application. -->
<!-- See Tinfi top-level module for profile definition. -->
<!-- tinfi.run.component: component ADL type -->
<!-- tinfi.run.interface: component server interface -->
<!-- ================================================== -->
<properties>
<tinfi.run.component>example.hw.HelloWorld</tinfi.run.component>
<tinfi.run.interface>r</tinfi.run.interface>
</properties>
<!-- ============================= -->
<!-- Dependency for generated code -->
<!-- ============================= -->
<dependencies>
<dependency>
<groupId>org.ow2.frascati.tinfi</groupId>
<artifactId>frascati-tinfi-runtime</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.objectweb.fractal.juliac</groupId>
<artifactId>maven-juliac-plugin</artifactId>
<version>${juliac.version}</version>
<executions>
<execution>
<id>juliac-compile</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<srcs><src>src/main/java</src></srcs>
<opt>org.ow2.frascati.tinfi.juliac.FCOOCtrlSourceCodeGenerator</opt>
<mixins>
<mixin>org.ow2.frascati.tinfi:frascati-tinfi-mixins:${project.version}:sources</mixin>
<mixin>org.objectweb.fractal.julia:julia-mixins:${julia.version}:sources</mixin>
</mixins>
<adls><adl>example.hw.HelloWorld</adl></adls>
<modules>
<module>org.ow2.frascati.tinfi:frascati-tinfi-compiler:${project.version}</module>
<module>org.objectweb.fractal.juliac:juliac-fractaladl:${juliac.version}</module>
<module>org.objectweb.fractal.juliac:juliac-jdt:${juliac.version}</module>
<module>org.objectweb.fractal.juliac:juliac-spoon:${juliac.version}</module>
</modules>
<!-- verbose>true</verbose -->
</configuration>
</plugin>
</plugins>
</build>
</project>
package example.hw;
public class ClientImpl implements Runnable {
public ClientImpl() {
System.err.println("CLIENT created");
}
public void run() {
s.print("hello world");
}
public void setS( Service s ) {
this.s = s;
}
private Service s;
}
\ No newline at end of file
package example.hw;
public class ServerImpl implements Service {
private String header = "->";
private int count = 1;
public ServerImpl() {
System.err.println("SERVER created");
}
public void print(final String msg) {
new Exception() {
private static final long serialVersionUID = 2182742162070453637L;
public String toString() {
return "Server: print method called";
}
}.printStackTrace();
System.err.println("Server: begin printing...");
for (int i = 0 ; i < (count) ; ++i) {
System.err.println(((header) + msg));
}
System.err.println("Server: print done.");
}
public String getHeader() {
return header;
}
public void setHeader(final String header) {
this.header = header;
}
public int getCount() {
return count;
}
public void setCount(final int count) {
this.count = count;
}
}
\ No newline at end of file
package example.hw;
public interface Service {
void print(String msg);
}
\ No newline at end of file
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE definition PUBLIC "-//objectweb.org//DTD Fractal ADL 2.0//EN" "classpath://org/objectweb/fractal/adl/xml/standard.dtd">
<definition name="example.hw.HelloWorld" >
<interface name="r" signature="java.lang.Runnable" role="server" />
<component name="client">
<interface name="r" signature="java.lang.Runnable" role="server" />
<interface name="s" signature="example.hw.Service" role="client" />
<content class="example.hw.ClientImpl"/>
<controller desc="scaPrimitive" />
</component>
<component name="server">
<interface name="s" signature="example.hw.Service" role="server" cardinality="singleton" contingency="mandatory"/>
<content class="example.hw.ServerImpl"/>
<controller desc="scaPrimitive"/>
</component>
<binding client="this.r" server="client.r" />
<binding client="client.s" server="server.s" />
</definition>
......@@ -16,6 +16,7 @@
<modules>
<module>foobar-cases</module>
<module>helloworld-bin</module>
<module>helloworld-pojo</module>
<module>helloworld-with-intent</module>
</modules>
......
To compile and run the example:
mvn -Ptinfi:run
/***
* Tinfi
* Copyright (C) 2008 INRIA, USTL
* Copyright (C) 2008-2009 INRIA, USTL
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -270,6 +270,50 @@ public class MetaData<T> {
return result;
}
/**
* <p>
* Return all unannotated setter methods. The query is performed on:
* </p>
*
* <ul>
* <li>methods declared in the support class,</li>
* <li>public methods inherited by the support class.</li>
* </ul>
*
* @return the corresponding map of methods indexed by property names
* (the property set by the method).
*/
public Map<String,Method> getAllUnAnnotatedSetterMethods() {
Map<String,Method> result = new HashMap<String,Method>();
// First, search in methods declared in the class
Method[] methods = cl.getDeclaredMethods();
for (Method method : methods) {
if( Util.isSetterMethod(method) ) {
Annotation[] annots = method.getAnnotations();
if( annots.length == 0 ) {
String prop = Util.getPropertyName(method);
result.put(prop,method);
}
}
}
// Second, search in declared and inherited public methods
methods = cl.getMethods();
for (Method method : methods) {
if( Util.isSetterMethod(method) ) {
Annotation[] annots = method.getAnnotations();
if( annots.length == 0 ) {
String prop = Util.getPropertyName(method);
result.put(prop,method);
}
}
}
return result;
}
/**
* <p>
* Return all constructors declared in the support class and associated with
......
/***
* Tinfi
* Copyright (C) 2007-2009 INRIA, USTL
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Lionel.Seinturier@univ-lille1.fr
*
* Author: Lionel Seinturier
*/
package org.ow2.frascati.tinfi.metadata;
import java.lang.reflect.Method;
/**
* Utility methods.
*
* @author Lionel Seinturier <Lionel.Seinturier@univ-lille1.fr>
* @since 0.4.4
*/
public class Util {
/**
* Return <code>true</code> if the specified method is a setter method.
*
* @param setter a setter method
* @return <code>true</code> if <code>setter</code> is a setter method
*/
public static boolean isSetterMethod( Method setter ) {
String name = setter.getName();
if( ! name.startsWith("set") ) {
return false;
}
Class<?> rtype = setter.getReturnType();
if( ! rtype.equals(void.class) ) {
return false;
}
Class<?>[] ptypes = setter.getParameterTypes();
if( ptypes.length != 1 ) {
return false;
}
return true;
}
/**
* Return the name of the property set by the specified setter method.
*
* @param setter a setter method
* @return the name of the property set by <code>setter</code>
* @throws IllegalArgumentException
* if <code>setter</code> is not a setter method
*/
public static String getPropertyName( Method setter ) {
if( ! isSetterMethod(setter) ) {
String msg = setter.toString() + " is not a setter method";
throw new IllegalArgumentException(msg);
}
String name = setter.getName();
name = name.substring(3); // Skip set
name = name.substring(0,1).toLowerCase() + name.substring(1);
return name;
}
}
......@@ -125,6 +125,32 @@ public class AnnotatedElementsManager {
}
}
/**
* Register an annotated element with the specified name.
*
* @param name the name of the annotated element
*
* @throws AnnotatedElementNotFoundException
* if the reference does not exist
* @throws DuplicateAnnotatedElementException
* if the reference is declared more than once
*/
public void addReference( String name )
throws
AnnotatedElementNotFoundException, DuplicateAnnotatedElementException {
AccessibleObject[] aos = cmd.getAllAnnotatedMethodsAndFields(annot);
addReference(aos,name);
}
/**
* Return <code>true</code> if the set of managed reference names contains
* the specified name.
*/
public boolean containsReferenceName( String name ) {
return links.containsKey(name);
}
/**
* Return the set of managed reference names.
*/
......@@ -181,7 +207,7 @@ public class AnnotatedElementsManager {
}
try {
re.set(target, value);
re.set( target, value );
}
catch( IllegalAccessException e ) {
throw new IllegalAnnotatedElementOperationException(e);
......
/***
* Tinfi
* Copyright (C) 2008 INRIA, USTL
* Copyright (C) 2008-2009 INRIA, USTL
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -155,6 +155,9 @@ public class ContentClassMetaData {
/** List of properties. */
public AnnotatedElementsManager props;
/** The unannotated setter methods. */
public Map<String,Method> setters;
/** The fields or methods annotated with @{@link Callback}. */
public AccessibleObject[] callbacks;
......@@ -287,6 +290,11 @@ public class ContentClassMetaData {
throw new IllegalContentClassMetaData(e);
}
/*
* Retrieve the unannotated setter methods.
*/
setters = md.getAllUnAnnotatedSetterMethods();
/*
* Retrieve the callbacks declared in the content class.
*/
......
/***
* Tinfi
* Copyright (C) 2008 INRIA, USTL
* Copyright (C) 2008-2009 INRIA, USTL
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -31,6 +31,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
......@@ -199,7 +200,7 @@ public class AbstractScopeManager {
throws
InstantiationException, AnnotatedElementNotFoundException,
IllegalAccessException, InvocationTargetException,
IllegalAnnotatedElementOperationException {
IllegalAnnotatedElementOperationException, NoSuchInterfaceException {
/*
* Set the component context.
......@@ -208,13 +209,6 @@ public class AbstractScopeManager {
ccmd.contextAnnotatedElement.set(content,compCtx);
}
/*
* Set the component name.
*/
if( ccmd.contextAnnotatedElement != null ) {
ccmd.contextAnnotatedElement.set(content,compCtx);
}
/*
* Set the component name.
*/
......@@ -225,13 +219,29 @@ public class AbstractScopeManager {
/*
* Set references.
*
* I was previously interating on ccmd.refs.getReferenceNames() for
* injecting references. However POJO setters are not included in this
* set (it would be a bit difficult to decide whether they should be
* included in ccmd.refs or in ccmd.props).
*/
Set<String> names = ccmd.refs.getReferenceNames();
ComponentType ct = (ComponentType) comp.getFcType();
for (String name : names) {
try {
InterfaceType it = ct.getFcInterfaceType(name);
Object sr = getServiceReference(it);
InterfaceType[] its = ct.getFcInterfaceTypes();
for (InterfaceType it : its) {
String name = it.getFcItfName();
if( name.equals("component") || name.endsWith("-controller") ) {
// Skip control interfaces
continue;
}
if( ! it.isFcClientItf() ) {
// Skip server interfaces
continue;
}
Object sr = getServiceReference(it);
if( ccmd.refs.containsReferenceName(name) ) {
// @Reference annotation
ccmd.refs.set(content,name,sr); // Inject the reference
if( sr instanceof List ) {
// Collection references
......@@ -245,36 +255,72 @@ public class AbstractScopeManager {
checkMandatoryReferenceHasBeenSet(sr,name);
}
}
catch( NoSuchInterfaceException nsie ) {
Reference ref = (Reference) ccmd.refs.getAnnotation(name);
if( ref.required() ) {
String msg =
"Mandatory reference "+name+" in component "+
nc.getFcName()+" should have been set";
throw new InstantiationException(msg);
else {
if( ccmd.setters.containsKey(name) ) {
// POJO
Method setter = ccmd.setters.get(name);
setter.invoke(content,sr);
}
else {
/*
* Indeed nothing.
*
* Neither an annotated case, nor a POJO. The reference may
* have been injected via an @Constructor annotation. See
* {@link #createFcInstance()}.
*/
// TODO we should be checking that all references have been injected either as a constructor, or as a annonated element or as a POJO
}
}
}
/*
* Set properties.
*
* I was previously interating on ccmd.props.getReferenceNames() for
* injecting property values. However POJO setters are not included in
* this set (it would be a bit difficult to decide whether they should
* be included in ccmd.refs or in ccmd.props).
*/
names = ccmd.props.getReferenceNames();
Map<String,Object> props = scapc.getAll();
for (Map.Entry<String,Object> entry : props.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
if( ccmd.props.containsReferenceName(name) ) {
// @Property annotation
ccmd.props.set(content,name,value);
}
else {
if( ccmd.setters.containsKey(name) ) {
// POJO
Method setter = ccmd.setters.get(name);
setter.invoke(content,value);
}
else {
/*
* Indeed nothing.
*
* Neither an annotated case, nor a POJO. The property value
* may have been injected via an @Constructor annotation.
* See {@link #createFcInstance()}.
*/
// TODO we should be checking that all properties have been injected either as a constructor, or as a annonated element or as a POJO
}
}
}
// Check that all mandatory properties have been set
Set<String> names = ccmd.props.getReferenceNames();
for (String name : names) {
if( ! scapc.containsKey(name) ) {
Property prop = (Property) ccmd.props.getAnnotation(name);
if( prop.required() ) {
String msg =
"Mandatory property(s) "+name+" in component "+
nc.getFcName()+
" should have been set";
nc.getFcName()+" should have been set";
throw new InstantiationException(msg);
}
}
else {
Object value = scapc.get(name);
ccmd.props.set(content,name,value);
}
}
/*
......@@ -321,8 +367,10 @@ public class AbstractScopeManager {
*
* @param sr the service reference
* @param name the name of the service reference
* @throws AnnotatedElementNotFoundException if the reference can not be found
* @throws InstantiationException if the reference has not been set
* @throws AnnotatedElementNotFoundException
* if the reference can not be found
* @throws InstantiationException
* if the reference has not been set
*/
private void checkMandatoryReferenceHasBeenSet( Object sr, String name )
throws AnnotatedElementNotFoundException, InstantiationException {
......@@ -345,7 +393,9 @@ public class AbstractScopeManager {
* Return the ServiceRefence (or the list of ServiceReference) associated to
* the specified InterfaceType.
*/
private Object getServiceReference( InterfaceType it ) throws NoSuchInterfaceException {
private Object getServiceReference( InterfaceType it )
throws NoSuchInterfaceException {
String name = it.getFcItfName();
if( it.isFcCollectionItf() ) {
Object[] itfs = comp.getFcInterfaces();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment