diff options
author | slaws <slaws@13f79535-47bb-0310-9956-ffa450edef68> | 2009-07-06 07:23:44 +0000 |
---|---|---|
committer | slaws <slaws@13f79535-47bb-0310-9956-ffa450edef68> | 2009-07-06 07:23:44 +0000 |
commit | 5b67e082ce57df77acc72cd36569a05c9a2fa347 (patch) | |
tree | 2aae54f73b2a9bbd5b8ad71f8e605e82f4595fc5 /branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml | |
parent | aafdaec972cfe3439c6fe15c599d46d3e5f13fa9 (diff) |
Branch for 1.5.1
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@791397 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml')
10 files changed, 1977 insertions, 0 deletions
diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/Constants.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/Constants.java new file mode 100644 index 0000000000..92f980fdfe --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/Constants.java @@ -0,0 +1,64 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.implementation.spring.xml;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Constants used in Spring Application Context XML files.
+ */
+public interface Constants {
+
+ String SCA_NS = "http://www.springframework.org/schema/sca";
+ String SPRING_NS = "http://www.springframework.org/schema/beans";
+
+ String PROPERTY = "property";
+ QName SCAPROPERTY_ELEMENT = new QName(SCA_NS, PROPERTY);
+ QName PROPERTY_ELEMENT = new QName(SPRING_NS, PROPERTY);
+
+ String SERVICE = "service";
+ QName SERVICE_ELEMENT = new QName(SCA_NS, SERVICE);
+
+ String REFERENCE = "reference";
+ QName REFERENCE_ELEMENT = new QName(SCA_NS, REFERENCE);
+
+ String BEANS = "beans";
+ QName BEANS_ELEMENT = new QName(SPRING_NS, BEANS);
+
+ String IMPORT = "import";
+ QName IMPORT_ELEMENT = new QName(SPRING_NS, IMPORT);
+
+ String BEAN = "bean";
+ QName BEAN_ELEMENT = new QName(SPRING_NS, BEAN);
+
+ String CONSTRUCTORARG = "constructor-arg";
+ QName CONSTRUCTORARG_ELEMENT = new QName(SPRING_NS, CONSTRUCTORARG);
+
+ String LIST = "list";
+ QName LIST_ELEMENT = new QName(SPRING_NS, LIST);
+
+ String VALUE = "value";
+ QName VALUE_ELEMENT = new QName(SPRING_NS, VALUE);
+
+ String REF = "ref";
+ QName REF_ELEMENT = new QName(SPRING_NS, REF);
+
+ String APPLICATION_CONTEXT = "application-context.xml";
+}
diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java new file mode 100644 index 0000000000..629a72e22d --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <bean> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $ + */ +public class SpringBeanElement { + + private String id; + private String className; + private boolean innerBean = false; + private List<SpringPropertyElement> properties = new ArrayList<SpringPropertyElement>(); + private List<SpringConstructorArgElement> constructorargs = new ArrayList<SpringConstructorArgElement>(); + + public SpringBeanElement(String id, String className) { + this.id = id; + this.className = className; + } + + public String getClassName() { + return className; + } + + public String getId() { + return id; + } + + public List<SpringPropertyElement> getProperties() { + return properties; + } + + public void addProperty(SpringPropertyElement property) { + properties.add(property); + } + + public List<SpringConstructorArgElement> getCustructorArgs() { + return constructorargs; + } + + public void addCustructorArgs(SpringConstructorArgElement args) { + constructorargs.add(args); + } + + public boolean isInnerBean() { + return innerBean; + } + + public void setInnerBean(boolean innerBean) { + this.innerBean = innerBean; + } + +} // end class SpringBeanElement diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java new file mode 100644 index 0000000000..5b6cfcab5b --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +import java.util.List; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ComponentNameProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConstructorProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ContextProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.DestroyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.EagerInitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.InitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PolicyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PropertyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ResourceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ServiceProcessor; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Provides introspection functions for Spring beans + * This version leans heavily on the implementation-java classes + * + * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $ + */ +public class SpringBeanIntrospector { + + private JavaImplementationFactory javaImplementationFactory; + + /** + * The constructor sets up the various visitor elements that will be used to introspect + * the Spring bean and extract SCA information. + * + * @param assemblyFactory The Assembly Factory to use + * @param javaFactory The Java Interface Factory to use + * @param policyFactory The Policy Factory to use. + */ + public SpringBeanIntrospector(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory, + PolicyFactory policyFactory, + List<SpringConstructorArgElement> conArgs) { + + javaImplementationFactory = new DefaultJavaImplementationFactory(); + + // Create the list of class visitors + BaseJavaClassVisitor[] extensions = + new BaseJavaClassVisitor[] { + new ConstructorProcessor(assemblyFactory), + new ComponentNameProcessor(assemblyFactory), + new ContextProcessor(assemblyFactory), + new DestroyProcessor(assemblyFactory), + new EagerInitProcessor(assemblyFactory), + new InitProcessor(assemblyFactory), + new PropertyProcessor(assemblyFactory), + new ReferenceProcessor(assemblyFactory, javaFactory), + new ResourceProcessor(assemblyFactory), + new ServiceProcessor(assemblyFactory, javaFactory), + new SpringBeanPojoProcessor(assemblyFactory, javaFactory, conArgs), + new PolicyProcessor(assemblyFactory, policyFactory)}; + for (JavaClassVisitor extension : extensions) { + javaImplementationFactory.addClassVisitor(extension); + } + + } // end constructor + + /** + * Introspect a Spring Bean and extract the features important to SCA + * @param beanClass the Spring Bean class to introspect + * @param componentType the componentType that is filled in through the introspection + * process (assumed empty on invocation, filled on return + * @return a Map of property names to JavaElementImpl + * @throws ContributionResolveException - if there was a problem resolving the + * Spring Bean or its componentType + * + */ + public JavaImplementation introspectBean(Class<?> beanClass, ComponentType componentType) throws ContributionResolveException + { + if (componentType == null) + throw new ContributionResolveException("Introspect Spring bean: supplied componentType is null"); + + // Create a Java implementation ready for the introspection + JavaImplementation javaImplementation = javaImplementationFactory.createJavaImplementation(); + + try { + // Introspect the bean...the results of the introspection are placed into the Java implementation + javaImplementationFactory.createJavaImplementation(javaImplementation, beanClass); + + // Extract the services, references & properties found through introspection + // put the services, references and properties into the component type + componentType.getServices().addAll(javaImplementation.getServices()); + componentType.getReferences().addAll(javaImplementation.getReferences()); + componentType.getProperties().addAll(javaImplementation.getProperties()); + + } catch (IntrospectionException e) { + throw new ContributionResolveException(e); + } // end try + + /* List<Service> services = javaImplementation.getServices(); + for (Service service : services) { + String name = service.getName(); + System.out.println("Spring Bean: found service with name: " + name); + } // end for */ + + return javaImplementation; + + } // end method introspectBean + +} // end class SpringBeanIntrospector diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java new file mode 100644 index 0000000000..fe632190ee --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java @@ -0,0 +1,656 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.implementation.spring.xml;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllInterfaces;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getPrivateFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllPublicAndProtectedFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.toPropertyName;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jws.WebService;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.IntrospectionException;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Context;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+
+import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.NoConstructorException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.AmbiguousConstructorException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.InvalidServiceType;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.Resource;
+
+/**
+ * Heuristically evaluates an un-annotated Java implementation type to determine
+ * services, references, and properties according to the algorithm described in
+ * the SCA Java Client and Implementation Model Specification <p/> TODO
+ * Implement: <p/> When no service interface is annotated, need to calculate a
+ * single service comprising all public methods that are not reference or
+ * property injection sites. If that service can be exactly mapped to an
+ * interface implemented by the class then the service interface will be defined
+ * in terms of that interface.
+ *
+ * @version $Rev: 689426 $ $Date: 2008-08-27 14:56:06 +0530 (Wed, 27 Aug 2008) $
+ */
+public class SpringBeanPojoProcessor extends BaseJavaClassVisitor {
+ private JavaInterfaceFactory javaFactory;
+ private List<SpringConstructorArgElement> conArgs;
+
+ public SpringBeanPojoProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory, List<SpringConstructorArgElement> conArgs) {
+ super(assemblyFactory);
+ this.javaFactory = javaFactory;
+ this.conArgs = conArgs;
+ }
+
+ @Override
+ public <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ List<org.apache.tuscany.sca.assembly.Service> services = type.getServices();
+ if (services.isEmpty()) {
+ // heuristically determine the service
+ /**
+ * The following is quoted from Java Specification 1.2.1.3. Introspecting services offered by a Java implementation
+ * In the cases described below, the services offered by a Java implementation class may be determined
+ * through introspection, eliding the need to specify them using @Service. The following algorithm is used
+ * to determine how services are introspected from an implementation class:
+ *
+ * If the interfaces of the SCA services are not specified with the @Service annotation on the
+ * implementation class, it is assumed that all implemented interfaces that have been annotated
+ * as @Remotable are the service interfaces provided by the component. If none of the implemented
+ * interfaces is remotable, then by default the implementation offers a single service whose type
+ * is the implementation class.
+ */
+ Set<Class> interfaces = getAllInterfaces(clazz);
+ for (Class<?> i : interfaces) {
+ if (i.isAnnotationPresent(Remotable.class) || i.isAnnotationPresent(WebService.class)) {
+ addService(type, i);
+ }
+ }
+ if (services.isEmpty()) {
+ // class is the interface
+ addService(type, clazz);
+ }
+ }
+ Set<Method> methods = getAllUniquePublicProtectedMethods(clazz, false);
+ if (!type.getReferenceMembers().isEmpty() || !type.getPropertyMembers().isEmpty()) {
+ // references and properties have been explicitly defined
+ // if (type.getServices().isEmpty()) {
+ // calculateServiceInterface(clazz, type, methods);
+ // if (type.getServices().isEmpty()) {
+ // throw new ServiceTypeNotFoundException(clazz.getName());
+ // }
+ // }
+ evaluateConstructor(type, clazz);
+ return;
+ }
+ calcPropRefs(methods, services, type, clazz);
+ evaluateConstructor(type, clazz);
+ }
+
+ private void addService(JavaImplementation type, Class<?> clazz) throws IntrospectionException {
+ try {
+ org.apache.tuscany.sca.assembly.Service service = createService(clazz);
+ type.getServices().add(service);
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ }
+
+ private boolean isPublicSetter(Method method) {
+ return method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())
+ && method.getName().startsWith("set")
+ && method.getReturnType() == void.class;
+ }
+
+ private boolean isProtectedSetter(Method method) {
+ return method.getParameterTypes().length == 1 && Modifier.isProtected(method.getModifiers())
+ && method.getName().startsWith("set")
+ && method.getReturnType() == void.class;
+ }
+
+ private <T> void calcPropRefs(Set<Method> methods,
+ List<org.apache.tuscany.sca.assembly.Service> services,
+ JavaImplementation type,
+ Class<T> clazz) throws IntrospectionException {
+ // heuristically determine the properties references
+ // make a first pass through all public methods with one param
+ Set<String> setters = new HashSet<String>();
+ Set<String> others = new HashSet<String>();
+ for (Method method : methods) {
+ if (!isPublicSetter(method)) {
+ continue;
+ }
+ if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) {
+ // Add the property name as others
+ others.add(toPropertyName(method.getName()));
+ continue;
+ }
+ if (!isInServiceInterface(method, services)) {
+ // Not part of the service interface
+ String name = toPropertyName(method.getName());
+ setters.add(name);
+ // avoid duplicate property or ref names
+ if (!type.getPropertyMembers().containsKey(name) && !type.getReferenceMembers().containsKey(name)) {
+ Class<?> param = method.getParameterTypes()[0];
+ Type genericType = method.getGenericParameterTypes()[0];
+ if (isReferenceType(param, genericType)) {
+ type.getReferences().add(createReference(name, param));
+ type.getReferenceMembers().put(name, new JavaElementImpl(method, 0));
+ } else {
+ type.getProperties().add(createProperty(name, param));
+ type.getPropertyMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ }
+ }
+ }
+ // second pass for protected methods with one param
+ for (Method method : methods) {
+ if (!isProtectedSetter(method)) {
+ continue;
+ }
+ if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) {
+ // Add the property name as others
+ others.add(toPropertyName(method.getName()));
+ continue;
+ }
+ Class<?> param = method.getParameterTypes()[0];
+ String name = toPropertyName(method.getName());
+ setters.add(name);
+ // avoid duplicate property or ref names
+ if (isReferenceType(param, method.getGenericParameterTypes()[0])) {
+ if (!type.getReferenceMembers().containsKey(name)) {
+ type.getReferences().add(createReference(name, param));
+ type.getReferenceMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ } else {
+ if (!type.getPropertyMembers().containsKey(name)) {
+ type.getProperties().add(createProperty(name, param));
+ type.getPropertyMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ }
+ }
+
+ // Public or protected fields unless there is a public or protected
+ // setter method
+ // for the same name
+ Set<Field> fields = getAllPublicAndProtectedFields(clazz, false);
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(Callback.class) || field.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ if (setters.contains(field.getName()) || others.contains(field.getName())) {
+ continue;
+ }
+ String name = field.getName();
+ Class<?> paramType = field.getType();
+ if (isReferenceType(paramType, field.getGenericType())) {
+ if (!type.getReferenceMembers().containsKey(name)) {
+ type.getReferences().add(createReference(name, paramType));
+ type.getReferenceMembers().put(name, new JavaElementImpl(field));
+ }
+ } else {
+ if (!type.getPropertyMembers().containsKey(name)) {
+ type.getProperties().add(createProperty(name, paramType));
+ type.getPropertyMembers().put(name, new JavaElementImpl(field));
+ }
+ }
+ }
+
+ // Private fields unless there is a public or protected
+ // setter method for the same name
+ Set<Field> privateFields = getPrivateFields(clazz);
+ for (Field field : privateFields) {
+ if (field.isAnnotationPresent(Callback.class) || field.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ if (setters.contains(field.getName()) || others.contains(field.getName())) {
+ continue;
+ }
+ String name = field.getName();
+ Class<?> paramType = field.getType();
+ if (isReferenceType(paramType, field.getGenericType())) {
+ if (!type.getReferenceMembers().containsKey(name)) {
+ type.getReferences().add(createReference(name, paramType));
+ type.getReferenceMembers().put(name, new JavaElementImpl(field));
+ }
+ } else {
+ if (!type.getPropertyMembers().containsKey(name)) {
+ type.getProperties().add(createProperty(name, paramType));
+ type.getPropertyMembers().put(name, new JavaElementImpl(field));
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines the constructor to use based on the component type's
+ * references and properties
+ *
+ * @param type the component type
+ * @param clazz the implementation class corresponding to the component type
+ * @throws NoConstructorException if no suitable constructor is found
+ * @throws AmbiguousConstructorException if the parameters of a constructor
+ * cannot be unambiguously mapped to references and properties
+ */
+ @SuppressWarnings("unchecked")
+ private <T> void evaluateConstructor(JavaImplementation type, Class<T> clazz) throws IntrospectionException {
+ // determine constructor if one is not annotated
+ JavaConstructorImpl<?> definition = type.getConstructor();
+ Map<String, JavaElementImpl> props = type.getPropertyMembers();
+ Map<String, JavaElementImpl> refs = type.getReferenceMembers();
+ Constructor constructor;
+ boolean explict = false;
+ if (definition != null && definition.getConstructor()
+ .isAnnotationPresent(org.osoa.sca.annotations.Constructor.class)) {
+ // the constructor was already defined explicitly
+ return;
+ } else if (definition != null) {
+ explict = true;
+ constructor = definition.getConstructor();
+ } else {
+ // no definition, heuristically determine constructor
+ Constructor[] constructors = clazz.getConstructors();
+ if (constructors.length == 0) {
+ throw new NoConstructorException("No public constructor for class");
+ } else if (constructors.length == 1) {
+ // Only one constructor, take it
+ constructor = constructors[0];
+ } else {
+ // multiple constructors scenario
+ Constructor<T> selected = null;
+ for (Constructor<T> ctor : constructors) {
+ if (ctor.getParameterTypes().length == 0) {
+ selected = ctor;
+ } else if (ctor.getParameterTypes().length == conArgs.size()) {
+ // we will find a constructor which has atleast one
+ // reference or property as its parameter types.
+ Class<?>[] parametersTypes = ctor.getParameterTypes();
+ for (Class<?> pType: parametersTypes) {
+ for (JavaElementImpl property : props.values()) {
+ if (pType.equals(property.getType()))
+ selected = ctor;
+ }
+ for (JavaElementImpl reference : refs.values()) {
+ if (pType.equals(reference.getType()))
+ selected = ctor;
+ }
+ }
+ }
+ }
+ if (selected == null) {
+ throw new NoConstructorException();
+ }
+ constructor = selected;
+ }
+ definition = type.getConstructors().get(constructor);
+ type.setConstructor(definition);
+ }
+
+ JavaParameterImpl[] parameters = definition.getParameters();
+ if (parameters.length == 0) {
+ return;
+ }
+
+ Annotation[][] annotations = constructor.getParameterAnnotations();
+ if (!explict) {
+ // the constructor wasn't defined by an annotation, so check to see
+ // if any of the params have an annotation
+ // which we can impute as explicitly defining the constructor, e.g.
+ // @Property, @Reference, or @Autowire
+ explict = injectionAnnotationsPresent(annotations);
+ }
+ if (explict) {
+ for (int i = 0; i < parameters.length; i++) {
+ if (isAnnotated(parameters[i])) {
+ continue;
+ } else if (!findReferenceOrProperty(parameters[i], props, refs)) {
+ throw new AmbiguousConstructorException(parameters[i].toString());
+ }
+ }
+ } else {
+ if (!areUnique(parameters)) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!calcPropRefUniqueness(props.values(), refs.values())) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!(props.isEmpty() && refs.isEmpty())) {
+ calcParamNames(parameters, props, refs);
+ } else {
+ heuristicParamNames(type, parameters);
+
+ }
+ }
+ }
+
+ private void calcParamNames(JavaParameterImpl[] parameters,
+ Map<String, JavaElementImpl> props,
+ Map<String, JavaElementImpl> refs) throws AmbiguousConstructorException {
+ // the constructor param types must unambiguously match defined
+ // reference or property types
+ for (JavaParameterImpl param : parameters) {
+ if (!findReferenceOrProperty(param, props, refs)) {
+ throw new AmbiguousConstructorException(param.getName());
+ }
+ }
+ }
+
+ private void heuristicParamNames(JavaImplementation type, JavaParameterImpl[] parameters)
+ throws IntrospectionException {
+ // heuristically determine refs and props from the parameter types
+ for (JavaParameterImpl p : parameters) {
+ String name = p.getType().getSimpleName().toLowerCase();
+ if (isReferenceType(p.getType(), p.getGenericType())) {
+ type.getReferences().add(createReference(name, p.getType()));
+ p.setClassifer(Reference.class);
+ type.getReferenceMembers().put(name, p);
+ } else {
+ type.getProperties().add(createProperty(name, p.getType()));
+ p.setClassifer(Property.class);
+ type.getPropertyMembers().put(name, p);
+ }
+ p.setName(name);
+ }
+ }
+
+ private static boolean areUnique(Class[] collection) {
+ Set<Class> set = new HashSet<Class>(Arrays.asList(collection));
+ return set.size() == collection.length;
+ }
+
+ /**
+ * Returns true if the union of the given collections of properties and
+ * references have unique Java types
+ */
+ private boolean calcPropRefUniqueness(Collection<JavaElementImpl> props, Collection<JavaElementImpl> refs) {
+
+ Class[] classes = new Class[props.size() + refs.size()];
+ int i = 0;
+ for (JavaElementImpl property : props) {
+ classes[i] = property.getType();
+ i++;
+ }
+ for (JavaElementImpl reference : refs) {
+ classes[i] = reference.getType();
+ i++;
+ }
+ return areUnique(classes);
+ }
+
+ /**
+ * Unambiguously finds the reference or property associated with the given
+ * type
+ *
+ * @return the name of the reference or property if found, null if not
+ * @throws AmbiguousConstructorException if the constructor parameter cannot
+ * be resolved to a property or reference
+ */
+ private boolean findReferenceOrProperty(JavaParameterImpl parameter,
+ Map<String, JavaElementImpl> props,
+ Map<String, JavaElementImpl> refs) throws AmbiguousConstructorException {
+
+ boolean found = false;
+ if (!"".equals(parameter.getName())) {
+ // Match by name
+ JavaElementImpl prop = props.get(parameter.getName());
+ if (prop != null && prop.getType() == parameter.getType()) {
+ parameter.setClassifer(Property.class);
+ return true;
+ }
+ JavaElementImpl ref = refs.get(parameter.getName());
+ if (ref != null && ref.getType() == parameter.getType()) {
+ parameter.setClassifer(Reference.class);
+ return true;
+ }
+ }
+ for (JavaElementImpl property : props.values()) {
+ if (property.getType() == parameter.getType()) {
+ if (found) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ (Member)parameter.getAnchor());
+ }
+ parameter.setClassifer(Property.class);
+ parameter.setName(property.getName());
+ found = true;
+ // do not break since ambiguities must be checked, i.e. more
+ // than one prop or ref of the same type
+ }
+ }
+ for (JavaElementImpl reference : refs.values()) {
+ if (reference.getType() == parameter.getType()) {
+ if (found) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ (Member)parameter.getAnchor());
+ }
+ parameter.setClassifer(Reference.class);
+ parameter.setName(reference.getName());
+ found = true;
+ // do not break since ambiguities must be checked, i.e. more
+ // than one prop or ref of the same type
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Returns true if a given type is reference according to the SCA
+ * specification rules for determining reference types The following rules
+ * are used to determine whether an unannotated field or setter method is a
+ * property or reference:
+ * <ol>
+ * <li>If its type is simple, then it is a property.
+ * <li>If its type is complex, then if the type is an interface marked by
+ *
+ * @Remotable, then it is a reference; otherwise, it is a property.
+ * <li>Otherwise, if the type associated with the member is an
+ * array or a java.util.Collection, the basetype is the element
+ * type of the array or the parameterized type of the
+ * Collection; otherwise the basetype is the member type. If the
+ * basetype is an interface with an
+ * @Remotable or
+ * @Service annotation then the member is defined as a reference. Otherwise,
+ * it is defined as a property.
+ * </ol>
+ * <p>
+ * The name of the reference or of the property is derived from the
+ * name found on the setter method or on the field.
+ */
+ private boolean isReferenceType(Class<?> cls, Type genericType) {
+ Class<?> baseType = JavaIntrospectionHelper.getBaseType(cls, genericType);
+ return baseType.isInterface() && baseType.isAnnotationPresent(Remotable.class);
+ }
+
+ /**
+ * Returns true if the given operation is defined in the collection of
+ * service interfaces
+ */
+ private boolean isInServiceInterface(Method operation, List<org.apache.tuscany.sca.assembly.Service> services) {
+ for (org.apache.tuscany.sca.assembly.Service service : services) {
+ Interface interface1 = service.getInterfaceContract().getInterface();
+ if (interface1 instanceof JavaInterface) {
+ Class<?> clazz = ((JavaInterface)interface1).getJavaClass();
+ if (isMethodMatched(clazz, operation)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test if the class declares a method which matches the signature of the
+ * given method
+ *
+ * @param clazz
+ * @param method
+ * @return
+ */
+ private boolean isMethodMatched(Class<?> clazz, Method method) {
+ if (method.getDeclaringClass() == clazz) {
+ return true;
+ }
+ Method[] methods = clazz.getMethods();
+ for (Method m : methods) {
+ if (JavaIntrospectionHelper.exactMethodMatch(method, m)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a mapped property.
+ *
+ * @param name the property name
+ * @param paramType the property type
+ */
+ private org.apache.tuscany.sca.assembly.Property createProperty(String name, Class<?> paramType) {
+ org.apache.tuscany.sca.assembly.Property property = assemblyFactory.createProperty();
+ property.setName(name);
+ property.setXSDType(JavaXMLMapper.getXMLType(paramType));
+ return property;
+ }
+
+ private boolean isAnnotated(JavaParameterImpl parameter) {
+ for (Annotation annotation : parameter.getAnnotations()) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class) || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean areUnique(JavaParameterImpl[] parameters) {
+ Set<Class> set = new HashSet<Class>(parameters.length);
+ for (JavaParameterImpl p : parameters) {
+ if (!set.add(p.getType())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public org.apache.tuscany.sca.assembly.Reference createReference(String name, Class<?> paramType)
+ throws IntrospectionException {
+ org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference();
+ reference.setName(name);
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+ try {
+ JavaInterface callInterface = javaFactory.createJavaInterface(paramType);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass());
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ } catch (InvalidInterfaceException e1) {
+ throw new IntrospectionException(e1);
+ }
+
+ // FIXME: This part seems to have already been taken care above!!
+ try {
+ processCallback(paramType, reference);
+ } catch (InvalidServiceType e) {
+ throw new IntrospectionException(e);
+ }
+ return reference;
+ }
+
+ public org.apache.tuscany.sca.assembly.Service createService(Class<?> interfaze) throws InvalidInterfaceException {
+ org.apache.tuscany.sca.assembly.Service service = assemblyFactory.createService();
+ service.setName(interfaze.getSimpleName());
+
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ JavaInterface callInterface = javaFactory.createJavaInterface(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+
+ Interface javaInterface = service.getInterfaceContract().getInterface();
+ javaInterface.setRemotable(interfaze.getAnnotation(Remotable.class) != null);
+ service.getInterfaceContract().setInterface(javaInterface);
+ return service;
+ }
+
+ public void processCallback(Class<?> interfaze, Contract contract) throws InvalidServiceType {
+ Callback callback = interfaze.getAnnotation(Callback.class);
+ if (callback != null && !Void.class.equals(callback.value())) {
+ Class<?> callbackClass = callback.value();
+ JavaInterface javaInterface;
+ try {
+ javaInterface = javaFactory.createJavaInterface(callbackClass);
+ contract.getInterfaceContract().setCallbackInterface(javaInterface);
+ } catch (InvalidInterfaceException e) {
+ throw new InvalidServiceType("Invalid callback interface "+callbackClass, interfaze);
+ }
+ } else if (callback != null && Void.class.equals(callback.value())) {
+ throw new InvalidServiceType("No callback interface specified on annotation", interfaze);
+ }
+ }
+
+ public boolean injectionAnnotationsPresent(Annotation[][] annots) {
+ for (Annotation[] annotations : annots) {
+ for (Annotation annotation : annotations) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class) || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java new file mode 100644 index 0000000000..553b3d33dd --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java @@ -0,0 +1,78 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.implementation.spring.xml;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a <constructor-arg> element in a Spring application-context
+ * - this has ref attribute
+ *
+ * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $
+ */
+public class SpringConstructorArgElement {
+
+ private String ref;
+ private String type;
+ private int autoIndex = -1;
+ private int index = -1;
+ private List<String> values = new ArrayList<String>();
+
+ public SpringConstructorArgElement(String ref, String type) {
+ this.ref = ref;
+ this.type = type;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String getRef() {
+ return this.ref;
+ }
+
+ public void setRef(String ref) {
+ this.ref = ref;
+ }
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public int getAutoIndex() {
+ return this.autoIndex;
+ }
+
+ public void setAutoIndex(int index) {
+ this.autoIndex = index;
+ }
+
+ public List<String> getValues() {
+ return this.values;
+ }
+
+ public void addValue(String value) {
+ this.values.add(value);
+ }
+}
diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringPropertyElement.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringPropertyElement.java new file mode 100644 index 0000000000..c60fdb86a9 --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringPropertyElement.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a <property> element in a Spring application-context + * - this has name and ref attributes + * + * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $ + */ +public class SpringPropertyElement { + + private String name; + private String ref; + private List<String> values = new ArrayList<String>(); + + public SpringPropertyElement(String name, String ref) { + this.name = name; + this.ref = ref; + } + + public String getName() { + return name; + } + + public String getRef() { + return ref; + } + + public void setRef(String ref) { + this.ref = ref; + } + + public List<String> getValues() { + return this.values; + } + + public void addValue(String value) { + this.values.add(value); + } + +} // end class SpringPropertyElement diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAPropertyElement.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAPropertyElement.java new file mode 100644 index 0000000000..2f37ab6504 --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAPropertyElement.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +/** + * Represents an <sca:property> element in a Spring application-context + * - this has name and type attributes + * @version $Rev: 511195 $ $Date: 2007-02-24 02:29:46 +0000 (Sat, 24 Feb 2007) $ + */ +public class SpringSCAPropertyElement { + + private String name; + private String type; + + public SpringSCAPropertyElement(String name, String type) { + this.name = name; + this.type = type; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} // end class SpringPropertyElement diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAReferenceElement.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAReferenceElement.java new file mode 100644 index 0000000000..b3f45415fd --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAReferenceElement.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +/** + * Represents a <sca:reference> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $ + */ +public class SpringSCAReferenceElement { + + private String name; + private String type; + + public SpringSCAReferenceElement(String name, String type) { + this.name = name; + this.type = type; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + +} // end class SpringSCAReferenceElement diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAServiceElement.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAServiceElement.java new file mode 100644 index 0000000000..2eb5686270 --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringSCAServiceElement.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +/** + * Represents a <sca:service> element in a Spring application-context + * - this has id and className attributes + * - plus zero or more property elements as children + * + * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $ + */ +public class SpringSCAServiceElement { + + private String name; + private String type; + private String target; + + public SpringSCAServiceElement(String name, String type, String target) { + this.name = name; + this.type = type; + this.target = target; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setType(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public void setTarget(String target) { + this.target = target; + } + + public String getTarget() { + return target; + } + +} // end class SpringSCAServiceElement diff --git a/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java new file mode 100644 index 0000000000..ef42e8c610 --- /dev/null +++ b/branches/sca-java-1.5.1/modules/implementation-spring-old/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java @@ -0,0 +1,739 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.spring.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; + +/** + * Introspects a Spring XML application-context configuration file to create <implementation-spring../> + * component type information. + * + * + * @version $Rev: 512919 $ $Date: 2007-02-28 19:32:56 +0000 (Wed, 28 Feb 2007) $ + */ +public class SpringXMLComponentTypeLoader { + + private AssemblyFactory assemblyFactory; + private JavaInterfaceFactory javaFactory; + private PolicyFactory policyFactory; + private ClassLoader cl; + + private SpringBeanIntrospector beanIntrospector; + private String contextPath; + + public SpringXMLComponentTypeLoader(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory, + PolicyFactory policyFactory) { + super(); + this.assemblyFactory = assemblyFactory; + this.javaFactory = javaFactory; + this.policyFactory = policyFactory; + } + + protected Class<SpringImplementation> getImplementationClass() { + return SpringImplementation.class; + } + + /** + * Base method which loads the component type from the application-context attached to the + * Spring implementation + * + */ + public void load(SpringImplementation implementation) throws ContributionReadException { + //System.out.println("Spring TypeLoader - load method start"); + ComponentType componentType = implementation.getComponentType(); + /* Check that there is a component type object already set */ + if (componentType == null) { + throw new ContributionReadException("SpringXMLLoader load: implementation has no ComponentType object"); + } + if (componentType.isUnresolved()) { + /* Fetch the location of the application-context file from the implementation */ + loadFromXML(implementation); + if (!componentType.isUnresolved()) + implementation.setUnresolved(false); + } // end if + //System.out.println("Spring TypeLoader - load method complete"); + } // end method load + + /** + * Method which fills out the component type for a Spring implementation by reading the + * Spring application-context.xml file. + * + * @param implementation SpringImplementation into which to load the component type information + * @throws ContributionReadException Failed to read the contribution + */ + private void loadFromXML(SpringImplementation implementation) throws ContributionReadException { + XMLStreamReader reader; + List<SpringBeanElement> beans = new ArrayList<SpringBeanElement>(); + List<SpringSCAServiceElement> services = new ArrayList<SpringSCAServiceElement>(); + List<SpringSCAReferenceElement> references = new ArrayList<SpringSCAReferenceElement>(); + List<SpringSCAPropertyElement> scaproperties = new ArrayList<SpringSCAPropertyElement>(); + + Resource resource; + + contextPath = implementation.getLocation(); + + try { + // FIXME - is the ContextClassLoader the right place to start the search? + cl = Thread.currentThread().getContextClassLoader(); + + resource = getApplicationContextResource(contextPath, cl); + implementation.setResource(resource); + // The URI is used to uniquely identify the Implementation + implementation.setURI(resource.getURL().toString()); + // FIXME - need a better way to handle the XMLInputFactory than allocating a new one every time + XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); + reader = xmlFactory.createXMLStreamReader(resource.getInputStream()); + + // System.out.println("Spring TypeLoader - starting to read context file"); + readContextDefinition(reader, beans, services, references, scaproperties); + + } catch (IOException e) { + throw new ContributionReadException(e); + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } + + /* At this point, the complete application-context.xml file has been read and its contents */ + /* stored in the lists of beans, services, references. These are now used to generate */ + /* the implied componentType for the application context */ + generateComponentType(implementation, beans, services, references, scaproperties); + + return; + } // end method loadFromXML + + /** + * Method which returns the XMLStreamReader for the Spring application-context.xml file + * specified in the location attribute + */ + private XMLStreamReader getApplicationContextReader(String location) throws ContributionReadException { + + try { + // FIXME - is the ContextClassLoader the right place to start the search? + cl = Thread.currentThread().getContextClassLoader(); + Resource resource = getApplicationContextResource(location, cl); + // FIXME - need a better way to handle the XMLInputFactory than allocating a new one every time + XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); + XMLStreamReader reader = xmlFactory.createXMLStreamReader(resource.getInputStream()); + return reader; + } catch (IOException e) { + throw new ContributionReadException(e); + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } + } + + /** + * Method which reads the spring context definitions from Spring application-context.xml + * file and identifies the defined beans, properties, services and references + */ + private void readContextDefinition(XMLStreamReader reader, + List<SpringBeanElement> beans, + List<SpringSCAServiceElement> services, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties) throws ContributionReadException { + + SpringBeanElement bean = null; + + try { + boolean completed = false; + while (!completed) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + //System.out.println("Spring TypeLoader - found element with name: " + qname.toString()); + if (Constants.IMPORT_ELEMENT.equals(qname)) { + //FIXME - put the sequence of code below which gets the ireader into a subsidiary method + String location = reader.getAttributeValue(null, "resource"); + if (location != null) { + // FIXME - need to find a right way of generating this path + String resourcePath = contextPath.substring(0, contextPath.lastIndexOf("/")+1) + location; + XMLStreamReader ireader = getApplicationContextReader(resourcePath); + // Read the context definition for the identified imported resource + readContextDefinition(ireader, beans, services, references, scaproperties); + } + } else if (Constants.SERVICE_ELEMENT.equals(qname)) { + SpringSCAServiceElement service = + new SpringSCAServiceElement(reader.getAttributeValue(null, "name"), reader + .getAttributeValue(null, "type"), reader.getAttributeValue(null, "target")); + services.add(service); + } else if (Constants.REFERENCE_ELEMENT.equals(qname)) { + SpringSCAReferenceElement reference = + new SpringSCAReferenceElement(reader.getAttributeValue(null, "name"), reader + .getAttributeValue(null, "type")); + references.add(reference); + } else if (Constants.SCAPROPERTY_ELEMENT.equals(qname)) { + SpringSCAPropertyElement scaproperty = + new SpringSCAPropertyElement(reader.getAttributeValue(null, "name"), reader + .getAttributeValue(null, "type")); + scaproperties.add(scaproperty); + } else if (Constants.BEAN_ELEMENT.equals(qname)) { + bean = new SpringBeanElement(reader.getAttributeValue(null, "id"), reader + .getAttributeValue(null, "class")); + beans.add(bean); + // Read the <bean> element and its child elements + readBeanDefinition(reader, bean, beans, services, references, scaproperties); + } // end if*/ + break; + case END_ELEMENT: + if (Constants.BEANS_ELEMENT.equals(reader.getName())) { + //System.out.println("Spring TypeLoader - finished read of context file"); + completed = true; + break; + } // end if + } // end switch + } // end while + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } + } + + + /** + * Method which reads the bean definitions from Spring application-context.xml file and identifies + * the defined beans, properties, services and references + */ + private void readBeanDefinition(XMLStreamReader reader, + SpringBeanElement bean, + List<SpringBeanElement> beans, + List<SpringSCAServiceElement> services, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties) throws ContributionReadException { + + SpringBeanElement innerbean = null; + SpringPropertyElement property = null; + SpringConstructorArgElement constructorArg = null; + int autoConstructorIndex = -1; + + try { + boolean completed = false; + while (!completed) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (Constants.BEAN_ELEMENT.equals(qname)) { + innerbean = new SpringBeanElement(reader.getAttributeValue(null, "id"), reader + .getAttributeValue(null, "class")); + innerbean.setInnerBean(true); + beans.add(innerbean); + readBeanDefinition(reader, innerbean, beans, services, references, scaproperties); + } else if (Constants.PROPERTY_ELEMENT.equals(qname)) { + property = new SpringPropertyElement(reader.getAttributeValue(null, "name"), reader + .getAttributeValue(null, "ref")); + bean.addProperty(property); + } else if (Constants.CONSTRUCTORARG_ELEMENT.equals(qname)) { + constructorArg = new SpringConstructorArgElement(reader.getAttributeValue(null, "ref"), + reader.getAttributeValue(null, "type")); + autoConstructorIndex++; + constructorArg.setAutoIndex(autoConstructorIndex); + if (reader.getAttributeValue(null, "index") != null) + constructorArg.setIndex((new Integer(reader.getAttributeValue(null, "index"))).intValue()); + if (reader.getAttributeValue(null, "value") != null) { + String value = reader.getAttributeValue(null, "value"); + constructorArg.addValue(value); + if ((value.indexOf(".xml") != -1)) { + if ((bean.getClassName().indexOf(".ClassPathXmlApplicationContext") != -1) || + (bean.getClassName().indexOf(".FileSystemXmlApplicationContext") != -1)) { + XMLStreamReader creader = getApplicationContextReader(value); + // Read the context definition for the constructor-arg resources + readContextDefinition(creader, beans, services, references, scaproperties); + } + } + } + bean.addCustructorArgs(constructorArg); + } else if (Constants.REF_ELEMENT.equals(qname)) { + String ref = reader.getAttributeValue(null, "bean"); + // Check if the parent element is a property + if (property != null) property.setRef(ref); + // Check if the parent element is a constructor-arg + if (constructorArg != null) constructorArg.setRef(ref); + } else if (Constants.VALUE_ELEMENT.equals(qname)) { + String value = reader.getElementText(); + // Check if the parent element is a constructor-arg + if (constructorArg != null) { + constructorArg.addValue(value); + // Identify the XML resource specified for the constructor-arg element + if ((value.indexOf(".xml") != -1)) { + if ((bean.getClassName().indexOf(".ClassPathXmlApplicationContext") != -1) || + (bean.getClassName().indexOf(".FileSystemXmlApplicationContext") != -1)) { + XMLStreamReader creader = getApplicationContextReader(value); + // Read the context definition for the constructor-arg resources + readContextDefinition(creader, beans, services, references, scaproperties); + } + } + } + } // end if + break; + case END_ELEMENT: + if (Constants.BEAN_ELEMENT.equals(reader.getName())) { + completed = true; + break; + } else if (Constants.PROPERTY_ELEMENT.equals(reader.getName())) { + property = null; + } else if (Constants.CONSTRUCTORARG_ELEMENT.equals(reader.getName())) { + constructorArg = null; + } // end if + } // end switch + } // end while + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } + } + + /** + * Generates the Spring implementation component type from the configuration contained in the + * lists of beans, services, references and scaproperties derived from the application context + */ + private void generateComponentType(SpringImplementation implementation, + List<SpringBeanElement> beans, + List<SpringSCAServiceElement> services, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties) throws ContributionReadException { + /* + * 1. Each sca:service becomes a service in the component type + * 2. Each sca:reference becomes a reference in the component type + * 3. Each sca:property becomes a property in the component type + * 4. IF there are no explicit service elements, each bean becomes a service + * 5. Each bean property which is a reference not pointing at another bean in the + * application context becomes a reference unless it is pointing at one of the references + * 6. Each bean property which is not a reference and which is not pointing + * at another bean in the application context becomes a property in the component type + */ + + JavaImplementation javaImplementation = null; + ComponentType componentType = implementation.getComponentType(); + + try { + // Deal with the services first.... + Iterator<SpringSCAServiceElement> its = services.iterator(); + while (its.hasNext()) { + SpringSCAServiceElement serviceElement = its.next(); + Class<?> interfaze = cl.loadClass(serviceElement.getType()); + Service theService = createService(interfaze, serviceElement.getName()); + componentType.getServices().add(theService); + // Add this service to the Service / Bean map + String beanName = serviceElement.getTarget(); + for (SpringBeanElement beanElement : beans) { + if (beanName.equals(beanElement.getId())) { + implementation.setBeanForService(theService, beanElement); + } + } // end for + } // end while + + // Next handle the references + Iterator<SpringSCAReferenceElement> itr = references.iterator(); + while (itr.hasNext()) { + SpringSCAReferenceElement referenceElement = itr.next(); + Class<?> interfaze = cl.loadClass(referenceElement.getType()); + Reference theReference = createReference(interfaze, referenceElement.getName()); + componentType.getReferences().add(theReference); + } // end while + + // Next handle the properties + Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator(); + while (itsp.hasNext()) { + SpringSCAPropertyElement scaproperty = itsp.next(); + // Create a component type property if the SCA property element has a name + // and a type declared... + if (scaproperty.getType() != null && scaproperty.getName() != null) { + Property theProperty = assemblyFactory.createProperty(); + theProperty.setName(scaproperty.getName()); + // Get the Java class and then an XSD element type for the property + Class<?> propType = Class.forName(scaproperty.getType()); + theProperty.setXSDType(JavaXMLMapper.getXMLType(propType)); + componentType.getProperties().add(theProperty); + // Remember the Java Class (ie the type) for this property + implementation.setPropertyClass(theProperty.getName(), propType); + } // end if + } // end while + + // Finally deal with the beans + Iterator<SpringBeanElement> itb; + // If there are no explicit service elements, then expose all the beans + if (services.isEmpty()) { + itb = beans.iterator(); + // Loop through all the beans found + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + // If its a innerBean, ignore it + if (beanElement.isInnerBean()) continue; + // Load the Spring bean class + Class<?> beanClass = cl.loadClass(beanElement.getClassName()); + // Introspect the bean + beanIntrospector = + new SpringBeanIntrospector(assemblyFactory, javaFactory, policyFactory, beanElement.getCustructorArgs()); + ComponentType beanComponentType = assemblyFactory.createComponentType(); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); + // Get the service interface defined by this Spring Bean and add to + // the component type of the Spring Assembly + List<Service> beanServices = beanComponentType.getServices(); + componentType.getServices().addAll(beanServices); + // Add these services to the Service / Bean map + for (Service beanService : beanServices) { + implementation.setBeanForService(beanService, beanElement); + } + } // end while + } // end if + + itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + // Ignore if the bean has no properties and constructor arguments + if (beanElement.getProperties().isEmpty() && beanElement.getCustructorArgs().isEmpty()) + continue; + + Class<?> beanClass = cl.loadClass(beanElement.getClassName()); + // Introspect the bean + beanIntrospector = + new SpringBeanIntrospector(assemblyFactory, javaFactory, policyFactory, beanElement.getCustructorArgs()); + ComponentType beanComponentType = assemblyFactory.createComponentType(); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); + Map<String, JavaElementImpl> propertyMap = javaImplementation.getPropertyMembers(); + JavaConstructorImpl constructor = javaImplementation.getConstructor(); + // Get the references by this Spring Bean and add the unresolved ones to + // the component type of the Spring Assembly + List<Reference> beanReferences = beanComponentType.getReferences(); + List<Property> beanProperties = beanComponentType.getProperties(); + + Iterator<SpringPropertyElement> itp = beanElement.getProperties().iterator(); + while (itp.hasNext()) { + SpringPropertyElement propertyElement = itp.next(); + if (propertyRefUnresolved(propertyElement.getRef(), beans, references, scaproperties)) { + // This means an unresolved reference from the spring bean... + for (Reference reference : beanReferences) { + if (propertyElement.getName().equals(reference.getName())) { + // The name of the reference in this case is the string in + // the @ref attribute of the Spring property element, NOT the + // name of the field in the Spring bean.... + reference.setName(propertyElement.getRef()); + componentType.getReferences().add(reference); + } // end if + } // end for + + // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type + for (Property scaproperty : beanProperties) { + if (propertyElement.getName().equals(scaproperty.getName())) { + // The name of the reference in this case is the string in + // the @ref attribute of the Spring property element, NOT the + // name of the field in the Spring bean.... + Class<?> interfaze = cl.loadClass((propertyMap.get(propertyElement.getName()).getType()).getName()); + Reference theReference = createReference(interfaze, propertyElement.getRef()); + implementation.setUnresolvedBeanRef(propertyElement.getRef(), theReference); + } // end if + } // end for + } // end if + } // end while + + Iterator<SpringConstructorArgElement> itcr = beanElement.getCustructorArgs().iterator(); + while (itcr.hasNext()) { + SpringConstructorArgElement conArgElement = itcr.next(); + if (propertyRefUnresolved(conArgElement.getRef(), beans, references, scaproperties)) { + for (JavaParameterImpl parameter : constructor.getParameters()) { + String paramType = parameter.getType().getName(); + Class<?> interfaze = cl.loadClass(paramType); + // Create a component type reference/property if the constructor-arg element has a + // type attribute OR index attribute declared... + if ((conArgElement.getType() != null && paramType.equals(conArgElement.getType())) || + (conArgElement.getIndex() != -1 && (conArgElement.getIndex() == parameter.getIndex())) || + (conArgElement.getAutoIndex() == parameter.getIndex())) + { + if (parameter.getClassifer().getName().equals("org.osoa.sca.annotations.Reference")) { + Reference theReference = createReference(interfaze, conArgElement.getRef()); + componentType.getReferences().add(theReference); + } + if (parameter.getClassifer().getName().equals("org.osoa.sca.annotations.Property")) { + // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type + // we might need to verify with the component definition later. + Reference theReference = createReference(interfaze, conArgElement.getRef()); + implementation.setUnresolvedBeanRef(conArgElement.getRef(), theReference); + } + } + } // end for + } // end if + } // end while + + } // end while + + } catch (ClassNotFoundException e) { + // Means that either an interface class, property class or a bean was not found + throw new ContributionReadException(e); + } catch (InvalidInterfaceException e) { + throw new ContributionReadException(e); + } catch (ContributionResolveException e) { + + } // end try + + // If we get here, the Spring assembly component type is resolved + componentType.setUnresolved(false); + implementation.setComponentType(componentType); + return; + } // end method generateComponentType + + /* + * Determines whether a reference attribute of a Spring property element is resolved either + * by a bean in the application context or by an SCA reference element or by an SCA property + * element + * @param ref - a String containing the name of the reference - may be null + * @param beans - a List of SpringBean elements + * @param references - a List of SCA reference elements + * @return true if the property is not resolved, false if it is resolved + */ + private boolean propertyRefUnresolved(String ref, + List<SpringBeanElement> beans, + List<SpringSCAReferenceElement> references, + List<SpringSCAPropertyElement> scaproperties) { + boolean unresolved = true; + + if (ref != null) { + // Scan over the beans looking for a match + Iterator<SpringBeanElement> itb = beans.iterator(); + while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + // Does the bean name match the ref? + if (ref.equals(beanElement.getId())) { + unresolved = false; + break; + } // end if + } // end while + // Scan over the SCA reference elements looking for a match + if (unresolved) { + Iterator<SpringSCAReferenceElement> itr = references.iterator(); + while (itr.hasNext()) { + SpringSCAReferenceElement referenceElement = itr.next(); + if (ref.equals(referenceElement.getName())) { + unresolved = false; + break; + } // end if + } // end while + } // end if + // Scan over the SCA property elements looking for a match + if (unresolved) { + Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator(); + while (itsp.hasNext()) { + SpringSCAPropertyElement propertyElement = itsp.next(); + if (ref.equals(propertyElement.getName())) { + unresolved = false; + break; + } // end if + } // end while + } // end if + } else { + // In the case where ref = null, the property is not going to be a reference of any + // kind and can be ignored + unresolved = false; + } // end if + + return unresolved; + + } // end method propertyRefUnresolved + + /** + * Gets hold of the application-context.xml file as a Spring resource + * @param locationAttr - the location attribute from the <implementation.spring../> element + * @param cl - the ClassLoader for the Spring implementation + */ + protected Resource getApplicationContextResource(String locationAttr, ClassLoader cl) + throws ContributionReadException { + File manifestFile = null; + File appXmlFile; + File locationFile = null; + + URL url = cl.getResource(locationAttr); + if (url != null) { + String path = url.getPath(); + locationFile = new File(path); + } else { + throw new ContributionReadException( + "SpringXMLLoader getApplicationContextResource: " + "unable to find resource file " + + locationAttr); + } + + if (locationFile.isDirectory()) { + try { + manifestFile = new File(locationFile, "META-INF"+ File.separator +"MANIFEST.MF"); + if (manifestFile.exists()) { + Manifest mf = new Manifest(new FileInputStream(manifestFile)); + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + appXmlFile = new File(locationFile, appCtxPath); + if (appXmlFile.exists()) { + return new UrlResource(appXmlFile.toURL()); + } + } + } + // no manifest-specified Spring context, use default + appXmlFile = new File(locationFile, "META-INF" + File.separator + "spring" + + File.separator + Constants.APPLICATION_CONTEXT); + if (appXmlFile.exists()) { + return new UrlResource(appXmlFile.toURL()); + } + } catch (IOException e) { + throw new ContributionReadException("Error reading manifest " + manifestFile); + } + } else { + if (locationFile.isFile() && locationFile.getName().endsWith(".jar")) { + try { + JarFile jf = new JarFile(locationFile); + JarEntry je; + Manifest mf = jf.getManifest(); + if (mf != null) { + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + je = jf.getJarEntry(appCtxPath); + if (je != null) { + // TODO return a Spring specific Resource type for jars + return new UrlResource(new URL("jar:" + locationFile.toURI().toURL() + "!/" + appCtxPath)); + } + } + } + je = jf.getJarEntry("META-INF" + "/" + "spring" + "/" + Constants.APPLICATION_CONTEXT); + if (je != null) { + return new UrlResource(new URL("jar:" + locationFile.toURI().toURL() + "!/" + Constants.APPLICATION_CONTEXT)); + } + } catch (IOException e) { + // bad archive + // TODO: create a more appropriate exception type + throw new ContributionReadException("SpringXMLLoader getApplicationContextResource: " + + " IO exception reading context file.", e); + } + } + else { + if (locationFile.getName().endsWith(".xml")) { + return new UrlResource(url); + } + else { + // Deal with the directory inside a jar file, in case the contribution itself is a JAR file. + try { + if (locationFile.getPath().indexOf(".jar") > 0) { + String jarEntry = url.getPath().substring(6, url.getPath().indexOf("!")); + JarFile jf = new JarFile(jarEntry); + JarEntry je = jf.getJarEntry(url.getPath().substring(url.getPath().indexOf("!/")+2) + + "/" + "META-INF" + "/" + "MANIFEST.MF"); + if (je != null) { + Manifest mf = new Manifest(jf.getInputStream(je)); + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + je = jf.getJarEntry(url.getPath().substring(url.getPath().indexOf("!/")+2) + "/" + appCtxPath); + if (je != null) { + return new UrlResource(new URL("jar:" + url.getPath() + "/" + appCtxPath)); + } + } + } + } + } catch (IOException e) { + throw new ContributionReadException("Error reading manifest " + manifestFile); + } + } + } + } + + throw new ContributionReadException("SpringXMLLoader getApplicationContextResource: " + + "META-INF/spring/" + Constants.APPLICATION_CONTEXT + "not found"); + } // end method getApplicationContextResource + + /** + * Creates a Service for the component type based on its name and Java interface + */ + public Service createService(Class<?> interfaze, String name) throws InvalidInterfaceException { + Service service = assemblyFactory.createService(); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + service.setInterfaceContract(interfaceContract); + + // Set the name for the service + service.setName(name); + + // Set the call interface and, if present, the callback interface + JavaInterface callInterface = javaFactory.createJavaInterface(interfaze); + service.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + service.getInterfaceContract().setCallbackInterface(callbackInterface); + } + return service; + } // end method createService + + /** + * Creates a Reference for the component type based on its name and Java interface + */ + private org.apache.tuscany.sca.assembly.Reference createReference(Class<?> interfaze, String name) + throws InvalidInterfaceException { + org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference(); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + reference.setInterfaceContract(interfaceContract); + + // Set the name of the reference to the supplied name and the multiplicity of the reference + // to 1..1 - for Spring implementations, this is the only multiplicity supported + reference.setName(name); + reference.setMultiplicity(Multiplicity.ONE_ONE); + + // Set the call interface and, if present, the callback interface + JavaInterface callInterface = javaFactory.createJavaInterface(interfaze); + reference.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + reference.getInterfaceContract().setCallbackInterface(callbackInterface); + } + + return reference; + } +} // end class SpringXMLComponentTypeLoader |