From 2ad26cd7431d5d1d0b333ec18212eb5db29fd537 Mon Sep 17 00:00:00 2001 From: ramkumar Date: Fri, 31 Oct 2008 12:52:47 +0000 Subject: Checkin for TUSCANY-2654, TUSCANY-2655 and TUSCANY-2656 git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@709400 13f79535-47bb-0310-9956-ffa450edef68 --- .../spring/annotations/CalculatorServiceImpl.java | 131 ++++++++++++ .../context-access/CalculatorService-context.xml | 3 + .../CalculatorService-context.xml | 41 ++++ .../spring/annotations/Calculator.composite | 60 ++++++ .../test/java/context/access/CalculatorClient.java | 4 +- .../java/context/access/ContextAccessTestCase.java | 32 +++ .../context/imports/ContextImportsTestCase.java | 32 +++ .../context/multiple/MultipleContextTestCase.java | 32 +++ .../implementation/policies/CalculatorClient.java | 2 - .../policies/ImplementationPoliciesTestCase.java | 32 +++ .../java/spring/annotations/CalculatorClient.java | 65 ++++++ .../annotations/SpringAnnotationsTestCase.java | 32 +++ .../spring/SpringImplementation.java | 37 +++- .../spring/SpringImplementationProvider.java | 25 ++- .../ComponentNameAnnotationProcessor.java | 151 ++++++++++++++ .../processor/ConstructorAnnotationProcessor.java | 119 +++++++++++ .../processor/InitDestroyAnnotationProcessor.java | 72 +++++++ .../processor/PropertyAnnotationProcessor.java | 220 +++++++++++++++++++++ .../processor/ReferenceAnnotationProcessor.java | 186 +++++++++++++++++ .../spring/xml/SpringBeanIntrospector.java | 12 +- .../spring/xml/SpringXMLComponentTypeLoader.java | 4 +- 21 files changed, 1280 insertions(+), 12 deletions(-) create mode 100644 java/sca/itest/spring/src/main/java/spring/annotations/CalculatorServiceImpl.java create mode 100644 java/sca/itest/spring/src/main/resources/META-INF/sca/spring-annotation/CalculatorService-context.xml create mode 100644 java/sca/itest/spring/src/main/resources/spring/annotations/Calculator.composite create mode 100644 java/sca/itest/spring/src/test/java/context/access/ContextAccessTestCase.java create mode 100644 java/sca/itest/spring/src/test/java/context/imports/ContextImportsTestCase.java create mode 100644 java/sca/itest/spring/src/test/java/context/multiple/MultipleContextTestCase.java create mode 100644 java/sca/itest/spring/src/test/java/implementation/policies/ImplementationPoliciesTestCase.java create mode 100644 java/sca/itest/spring/src/test/java/spring/annotations/CalculatorClient.java create mode 100644 java/sca/itest/spring/src/test/java/spring/annotations/SpringAnnotationsTestCase.java create mode 100644 java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java create mode 100644 java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java create mode 100644 java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java create mode 100644 java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java create mode 100644 java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java diff --git a/java/sca/itest/spring/src/main/java/spring/annotations/CalculatorServiceImpl.java b/java/sca/itest/spring/src/main/java/spring/annotations/CalculatorServiceImpl.java new file mode 100644 index 0000000000..0206849a53 --- /dev/null +++ b/java/sca/itest/spring/src/main/java/spring/annotations/CalculatorServiceImpl.java @@ -0,0 +1,131 @@ +/* + * 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 spring.annotations; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Service; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.ComponentName; + +import calculator.AddService; +import calculator.CalculatorService; +import calculator.DivideService; +import calculator.MultiplyService; +import calculator.SubtractService; + +/** + * An implementation of the Calculator service. + */ +@Service(CalculatorService.class) +public class CalculatorServiceImpl implements AddService, SubtractService, MultiplyService, DivideService { + + public AddService addService; // setter injection + + @Reference + public SubtractService subtractService; // field injection + + @Reference(name="multiplyService", required=false) + public MultiplyService multiply; // field injection (different reference and field name) + + public DivideService divide; // setter injection (different reference and field name) + + public String message; // setter injection + + @Property(name="message", required=false) + public String message2; // field injection + + public String componentName; + + @Init + public void initMethod () { + System.out.println("Init method is sucessfully called....."); + // Property value should be null here. + System.out.println("Property Value message is...." + message); + } + + @Destroy + public void destroyMethod () { + System.out.println("Component Name is...." + componentName); + System.out.println("Property Value message is...." + message); + System.out.println("Property Value message2 is...." + message2); + System.out.println("Destroy method is sucessfully called....."); + } + + @Reference + public void setAddService(AddService addService) { + this.addService = addService; + } + + public AddService getAddService() { + return addService; + } + + /*public void setSubtractService(SubtractService subtractService) { + this.subtractService = subtractService; + } + + public SubtractService getSubtractService() { + return subtractService; + }*/ + + @Reference(name="divideService", required=false) + public void setDivideService(DivideService divide) { + this.divide = divide; + } + + public DivideService getDivideService() { + return divide; + } + + /*public void setMultiplyService(MultiplyService multiplyService) { + this.multiplyService = multiplyService; + } + + public MultiplyService getMultiplyService() { + return multiplyService; + }*/ + + @ComponentName + public void setComponentName(String componentName) { + this.componentName = componentName; + } + + @Property + public void setMessage(String message) { + this.message = message; + } + + public double add(double n1, double n2) { + return addService.add(n1, n2); + } + + public double subtract(double n1, double n2) { + return subtractService.subtract(n1, n2); + } + + public double multiply(double n1, double n2) { + return multiply.multiply(n1, n2); + } + + public double divide(double n1, double n2) { + return divide.divide(n1, n2); + } +} diff --git a/java/sca/itest/spring/src/main/resources/META-INF/sca/context-access/CalculatorService-context.xml b/java/sca/itest/spring/src/main/resources/META-INF/sca/context-access/CalculatorService-context.xml index cac612fa83..87458b99a3 100644 --- a/java/sca/itest/spring/src/main/resources/META-INF/sca/context-access/CalculatorService-context.xml +++ b/java/sca/itest/spring/src/main/resources/META-INF/sca/context-access/CalculatorService-context.xml @@ -23,6 +23,9 @@ xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd"> + + diff --git a/java/sca/itest/spring/src/main/resources/META-INF/sca/spring-annotation/CalculatorService-context.xml b/java/sca/itest/spring/src/main/resources/META-INF/sca/spring-annotation/CalculatorService-context.xml new file mode 100644 index 0000000000..4110a9a7b7 --- /dev/null +++ b/java/sca/itest/spring/src/main/resources/META-INF/sca/spring-annotation/CalculatorService-context.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + diff --git a/java/sca/itest/spring/src/main/resources/spring/annotations/Calculator.composite b/java/sca/itest/spring/src/main/resources/spring/annotations/Calculator.composite new file mode 100644 index 0000000000..a8a1f5b703 --- /dev/null +++ b/java/sca/itest/spring/src/main/resources/spring/annotations/Calculator.composite @@ -0,0 +1,60 @@ + + + + + + + HelloWorld + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/sca/itest/spring/src/test/java/context/access/CalculatorClient.java b/java/sca/itest/spring/src/test/java/context/access/CalculatorClient.java index e0cc246fab..9b7202d951 100644 --- a/java/sca/itest/spring/src/test/java/context/access/CalculatorClient.java +++ b/java/sca/itest/spring/src/test/java/context/access/CalculatorClient.java @@ -46,13 +46,13 @@ public class CalculatorClient { if (ctx.containsBean("CalculatorServiceBean")) System.out.println("CalculatorServiceBean is now available for use..."); - /*CalculatorService calculatorService = + CalculatorService calculatorService = ((SCAClient)node).getService(CalculatorService.class, "CalculatorServiceComponent"); System.out.println("3 + 2=" + calculatorService.add(3, 2)); System.out.println("3 - 2=" + calculatorService.subtract(3, 2)); System.out.println("3 * 2=" + calculatorService.multiply(3, 2)); - System.out.println("3 / 2=" + calculatorService.divide(3, 2));*/ + System.out.println("3 / 2=" + calculatorService.divide(3, 2)); node.stop(); } diff --git a/java/sca/itest/spring/src/test/java/context/access/ContextAccessTestCase.java b/java/sca/itest/spring/src/test/java/context/access/ContextAccessTestCase.java new file mode 100644 index 0000000000..5feb293bc8 --- /dev/null +++ b/java/sca/itest/spring/src/test/java/context/access/ContextAccessTestCase.java @@ -0,0 +1,32 @@ +/* + * 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 context.access; + +import junit.framework.TestCase; + +/** + * Tests out the big bank service + * + */ +public class ContextAccessTestCase extends TestCase { + + public void testServer() throws Exception { + CalculatorClient.main(new String[] {""}); + } +} diff --git a/java/sca/itest/spring/src/test/java/context/imports/ContextImportsTestCase.java b/java/sca/itest/spring/src/test/java/context/imports/ContextImportsTestCase.java new file mode 100644 index 0000000000..3940bf65fa --- /dev/null +++ b/java/sca/itest/spring/src/test/java/context/imports/ContextImportsTestCase.java @@ -0,0 +1,32 @@ +/* + * 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 context.imports; + +import junit.framework.TestCase; + +/** + * Tests out the big bank service + * + */ +public class ContextImportsTestCase extends TestCase { + + public void testServer() throws Exception { + CalculatorClient.main(new String[] {""}); + } +} diff --git a/java/sca/itest/spring/src/test/java/context/multiple/MultipleContextTestCase.java b/java/sca/itest/spring/src/test/java/context/multiple/MultipleContextTestCase.java new file mode 100644 index 0000000000..75b296bf32 --- /dev/null +++ b/java/sca/itest/spring/src/test/java/context/multiple/MultipleContextTestCase.java @@ -0,0 +1,32 @@ +/* + * 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 context.multiple; + +import junit.framework.TestCase; + +/** + * Tests out the big bank service + * + */ +public class MultipleContextTestCase extends TestCase { + + public void testServer() throws Exception { + StockQuoteServer.main(new String[] {"1000"}); + } +} diff --git a/java/sca/itest/spring/src/test/java/implementation/policies/CalculatorClient.java b/java/sca/itest/spring/src/test/java/implementation/policies/CalculatorClient.java index 9755a13f0b..27e634d301 100644 --- a/java/sca/itest/spring/src/test/java/implementation/policies/CalculatorClient.java +++ b/java/sca/itest/spring/src/test/java/implementation/policies/CalculatorClient.java @@ -47,8 +47,6 @@ public class CalculatorClient { SCANodeFactory factory = SCANodeFactory.newInstance(); SCANode node = factory.createSCANodeFromClassLoader("implementation/policies/Calculator.composite", CalculatorServiceImpl.class.getClassLoader()); - //SCANode node = factory.createSCANode(new File("itest/spring/src/main/resources/implementation/policies/Calculator.composite").toURL().toString(), - //new SCAContribution("TestContribution", new File("itest/spring/src/main/resources/implementation/policies").toURL().toString())); node.start(); CalculatorService calculatorService = diff --git a/java/sca/itest/spring/src/test/java/implementation/policies/ImplementationPoliciesTestCase.java b/java/sca/itest/spring/src/test/java/implementation/policies/ImplementationPoliciesTestCase.java new file mode 100644 index 0000000000..1e759f98a0 --- /dev/null +++ b/java/sca/itest/spring/src/test/java/implementation/policies/ImplementationPoliciesTestCase.java @@ -0,0 +1,32 @@ +/* + * 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 implementation.policies; + +import junit.framework.TestCase; + +/** + * Tests out the big bank service + * + */ +public class ImplementationPoliciesTestCase extends TestCase { + + public void testServer() throws Exception { + CalculatorClient.main(new String[] {""}); + } +} diff --git a/java/sca/itest/spring/src/test/java/spring/annotations/CalculatorClient.java b/java/sca/itest/spring/src/test/java/spring/annotations/CalculatorClient.java new file mode 100644 index 0000000000..c21561a962 --- /dev/null +++ b/java/sca/itest/spring/src/test/java/spring/annotations/CalculatorClient.java @@ -0,0 +1,65 @@ +/* + * 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 spring.annotations; + +import java.io.File; + +import org.apache.tuscany.sca.node.SCAClient; +import org.apache.tuscany.sca.node.SCAContribution; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeFactory; + +import calculator.CalculatorService; +import calculator.CalculatorServiceImpl; + + +/** + * This client program shows how to create an SCA runtime, start it, + * and locate and invoke a SCA component + */ +public class CalculatorClient { + public static void main(String[] args) throws Exception { + + SCANodeFactory factory = SCANodeFactory.newInstance(); + SCANode node = factory.createSCANode(new File("src/main/resources/spring/annotations/Calculator.composite").toURL().toString(), + new SCAContribution("TestContribution", new File("src/main/resources/spring/annotations/").toURL().toString())); + node.start(); + + CalculatorService calculatorService = + ((SCAClient)node).getService(CalculatorService.class, "CalculatorServiceComponent"); + + System.out.println("3 + 2=" + calculatorService.add(3, 2)); + System.out.println("3 - 2=" + calculatorService.subtract(3, 2)); + System.out.println("3 * 2=" + calculatorService.multiply(3, 2)); + System.out.println("3 / 2=" + calculatorService.divide(3, 2)); + + /*calculatorService = + ((SCAClient)node).getService(CalculatorService.class, "AnotherCalculatorServiceComponent"); + + System.out.println("3 + 2=" + calculatorService.add(3, 2)); + System.out.println("3 - 2=" + calculatorService.subtract(3, 2)); + System.out.println("3 * 2=" + calculatorService.multiply(3, 2)); + System.out.println("3 / 2=" + calculatorService.divide(3, 2));*/ + + node.stop(); + System.out.println("Bye"); + } + +} diff --git a/java/sca/itest/spring/src/test/java/spring/annotations/SpringAnnotationsTestCase.java b/java/sca/itest/spring/src/test/java/spring/annotations/SpringAnnotationsTestCase.java new file mode 100644 index 0000000000..3a9ec4bbb2 --- /dev/null +++ b/java/sca/itest/spring/src/test/java/spring/annotations/SpringAnnotationsTestCase.java @@ -0,0 +1,32 @@ +/* + * 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 spring.annotations; + +import junit.framework.TestCase; + +/** + * Tests out the big bank service + * + */ +public class SpringAnnotationsTestCase extends TestCase { + + public void testServer() throws Exception { + CalculatorClient.main(new String[] {""}); + } +} diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java index ac3ab74f73..e4f62d3bb2 100644 --- a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java @@ -18,6 +18,7 @@ */ package org.apache.tuscany.sca.implementation.spring; +import java.lang.reflect.Method; import java.util.Hashtable; import java.util.List; @@ -28,6 +29,7 @@ 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.assembly.impl.ImplementationImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; import org.apache.tuscany.sca.implementation.spring.xml.SpringBeanElement; import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; import org.springframework.core.io.Resource; @@ -47,8 +49,15 @@ public class SpringImplementation extends ImplementationImpl implements Implemen // Mapping of Services to Beans private Hashtable serviceMap; // Mapping of property names to Java class - private Hashtable propertyMap; + private Hashtable propertyMap; private List policyHandlerClassNames = null; + + // Method marked with @Init annotation + private Method initMethod = null; + // Method marked with @Destroy annotation + private Method destroyMethod = null; + // Method marked with @Constructor annotation + private JavaConstructorImpl constructorDefinition = null; protected SpringImplementation() { this.location = null; @@ -79,6 +88,30 @@ public class SpringImplementation extends ImplementationImpl implements Implemen public Resource getResource() { return resource; } + + public JavaConstructorImpl getConstructor() { + return constructorDefinition; + } + + public void setConstructor(JavaConstructorImpl definition) { + this.constructorDefinition = definition; + } + + public Method getInitMethod() { + return initMethod; + } + + public void setInitMethod(Method initMethod) { + this.initMethod = initMethod; + } + + public Method getDestroyMethod() { + return destroyMethod; + } + + public void setDestroyMethod(Method destroyMethod) { + this.destroyMethod = destroyMethod; + } /* * Returns the componentType for this Spring implementation @@ -155,5 +188,5 @@ public class SpringImplementation extends ImplementationImpl implements Implemen public void setPolicyHandlerClassNames(List policyHandlerClassNames) { this.policyHandlerClassNames = policyHandlerClassNames; - } + } // end method setPolicyHandlerClassNames } diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java index 537a2c9a11..4717df2056 100644 --- a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java @@ -29,7 +29,15 @@ import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; import org.apache.tuscany.sca.provider.ImplementationProvider; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.apache.tuscany.sca.implementation.spring.processor.InitDestroyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.ReferenceAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.PropertyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.ConstructorAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.ComponentNameAnnotationProcessor; +import org.springframework.beans.factory.config.BeanPostProcessor; // TODO - create a working version of this class... /** @@ -62,7 +70,21 @@ public class SpringImplementationProvider implements ImplementationProvider { SCAParentApplicationContext scaParentContext = new SCAParentApplicationContext(component, implementation, proxyService, propertyValueObjectFactory); - springContext = new SCAApplicationContext(scaParentContext, implementation.getResource()); + //springContext = new SCAApplicationContext(scaParentContext, implementation.getResource()); + + XmlBeanFactory beanFactory = new XmlBeanFactory(implementation.getResource()); + BeanPostProcessor initDestroyProcessor = new InitDestroyAnnotationProcessor(); + beanFactory.addBeanPostProcessor(initDestroyProcessor); + BeanPostProcessor referenceProcessor = new ReferenceAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(referenceProcessor); + BeanPostProcessor propertyProcessor = new PropertyAnnotationProcessor(propertyValueObjectFactory, component); + beanFactory.addBeanPostProcessor(propertyProcessor); + BeanPostProcessor componentNameProcessor = new ComponentNameAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(componentNameProcessor); + BeanPostProcessor constructorProcessor = new ConstructorAnnotationProcessor(); + beanFactory.addBeanPostProcessor(constructorProcessor); + springContext = new GenericApplicationContext(beanFactory, scaParentContext); + } // end constructor public Invoker createInvoker(RuntimeComponentService service, Operation operation) { @@ -89,6 +111,7 @@ public class SpringImplementationProvider implements ImplementationProvider { */ public void stop() { // TODO - complete + springContext.close(); springContext.stop(); //System.out.println("SpringImplementationProvider: Spring context stopped"); } // end method stop diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java new file mode 100644 index 0000000000..cd0567f461 --- /dev/null +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java @@ -0,0 +1,151 @@ +/* + * 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.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; + +import org.springframework.util.Assert; +import org.springframework.beans.BeanUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; + +import org.osoa.sca.annotations.ComponentName; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +public class ComponentNameAnnotationProcessor implements BeanPostProcessor { + + private Class componentNameAnnotationType = ComponentName.class; + + private RuntimeComponent component; + + public ComponentNameAnnotationProcessor (RuntimeComponent component) { + this.component = component; + } + + /** + * Gets componentName annotation type. + */ + protected Class getComponentNameAnnotationType() { + return this.componentNameAnnotationType; + } + + /** + * Sets componentName annotation type. + */ + public void setComponentNameAnnotationType(Class componentNameAnnotationType) { + Assert.notNull(componentNameAnnotationType, "'componentNameAnnotationType' type must not be null."); + this.componentNameAnnotationType = componentNameAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + /** + *

Processes a beans fields for injection if it has a {@link Reference} annotation.

+ */ + protected void processAnnotation(final Object bean) { + + final Class clazz = bean.getClass(); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + Annotation annotation = field.getAnnotation(getComponentNameAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on static fields"); + } + + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on private fields"); + } + + ReflectionUtils.makeAccessible(field); + + if (field.getType().getName().equals("java.lang.String")) { + Object nameObj = component.getName(); + if (nameObj != null) + ReflectionUtils.setField(field, bean, nameObj); + } else { + throw new IllegalStateException("ComponentName annotation is supported only on java.lang.String field type."); + } + } + } + }); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + Annotation annotation = method.getAnnotation(getComponentNameAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on static methods"); + } + + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("ComponentName annotation is not supported on private methods"); + } + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException("ComponentName annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + + if (pd.getPropertyType().getName().equals("java.lang.String")) { + Object nameObj = component.getName(); + if (nameObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] { nameObj }); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } else { + throw new IllegalStateException("ComponentName annotation is supported only on java.lang.String field type."); + } + } + } + }); + } +} diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java new file mode 100644 index 0000000000..4dadf37189 --- /dev/null +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java @@ -0,0 +1,119 @@ +/* + * 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.processor; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Constructor; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.util.Assert; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.annotation.Autowired; + +public class ConstructorAnnotationProcessor extends InstantiationAwareBeanPostProcessorAdapter { + + private Class constructorAnnotationType + = org.osoa.sca.annotations.Constructor.class; + + private Class autowiredAnnotationType = Autowired.class; + + public ConstructorAnnotationProcessor () { + // Default constructor. + } + + /** + * Set the 'autowired' annotation type, to be used on constructors, fields, + * setter methods and arbitrary config methods. + */ + public void setAutowiredAnnotationType(Class autowiredAnnotationType) { + Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null"); + this.autowiredAnnotationType = autowiredAnnotationType; + } + + /** + * Return the 'autowired' annotation type. + */ + protected Class getAutowiredAnnotationType() { + return this.autowiredAnnotationType; + } + + /** + * Return the 'constructor' annotation type. + */ + protected Class getConstructorAnnotationType() { + return this.constructorAnnotationType; + } + + /** + * Sets the 'constructor' annotation type. + */ + public void setConstructorAnnotationType(Class constructorAnnotationType) { + Assert.notNull(constructorAnnotationType, "'constructorAnnotationType' type must not be null."); + this.constructorAnnotationType = constructorAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + public Constructor[] determineCandidateConstructors(Class beanClass, String beanName) throws BeansException { + /*Constructor[] declaredConstructors = beanClass.getDeclaredConstructors(); + Method[] declaredMethods = beanClass.getDeclaredMethods(); + List candidates = new ArrayList(declaredConstructors.length); + + for (int i = 0; i < declaredMethods.length; i++) { + Method method = declaredMethods[i]; + Annotation annotation = method.getAnnotation(getConstructorAnnotationType()); + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Constructor annotation is not supported on static methods"); + } + + if (candidates.size() == 1) { + throw new IllegalStateException("Only one method is allowed to have constructor annotation in a bean: " + method); + } + + candidates.add(method); + } + } + + return (Constructor[]) candidates.toArray(new Constructor[candidates.size()]);*/ + return null; + } +} diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java new file mode 100644 index 0000000000..44737bf9d1 --- /dev/null +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java @@ -0,0 +1,72 @@ +/* + * 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.processor; + +import java.lang.annotation.Annotation; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Destroy; +import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor; +import org.springframework.util.Assert; + +public class InitDestroyAnnotationProcessor extends InitDestroyAnnotationBeanPostProcessor { + + private static final long serialVersionUID = 0; + + private Class initAnnotationType = Init.class; + + private Class destroyAnnotationType = Destroy.class; + + /** + * Gets init annotation type. + */ + protected Class getInitAnnotationType() { + return this.initAnnotationType; + } + + /** + * Sets init annotation type. + */ + /*public void setInitAnnotationType(Class initAnnotationType) { + Assert.notNull(initAnnotationType, "Init annotation type must not be null."); + this.initAnnotationType = initAnnotationType; + }*/ + + /** + * Gets destroy annotation type. + */ + protected Class getDestroyAnnotationType() { + return this.destroyAnnotationType; + } + + /** + * Sets destroy annotation type. + */ + /*public void setDestroyAnnotationType(Class destroyAnnotationType) { + Assert.notNull(destroyAnnotationType, "Destroy annotation type must not be null."); + this.destroyAnnotationType = destroyAnnotationType; + }*/ + + public InitDestroyAnnotationProcessor () { + // Set the @Init annotation type + setInitAnnotationType(initAnnotationType); + + // Set the @Destroy annotation type + setDestroyAnnotationType(destroyAnnotationType); + } +} diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java new file mode 100644 index 0000000000..d8755c58f4 --- /dev/null +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java @@ -0,0 +1,220 @@ +/* + * 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.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.util.List; + +import org.springframework.util.Assert; +import org.springframework.beans.BeanUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; + +import org.osoa.sca.annotations.Property; +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +public class PropertyAnnotationProcessor implements BeanPostProcessor { + + private Class propertyAnnotationType = Property.class; + + private RuntimeComponent component; + + private JavaPropertyValueObjectFactory propertyFactory; + + public PropertyAnnotationProcessor (JavaPropertyValueObjectFactory propertyFactory, + RuntimeComponent component) { + this.propertyFactory = propertyFactory; + this.component = component; + } + + /** + * Gets property annotation type. + */ + protected Class getPropertyAnnotationType() { + return this.propertyAnnotationType; + } + + /** + * Sets property annotation type. + */ + public void setPropertyAnnotationType(Class propertyAnnotationType) { + Assert.notNull(propertyAnnotationType, "'propertyAnnotationType' type must not be null."); + this.propertyAnnotationType = propertyAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + /** + *

Processes a beans fields for injection if it has a {@link Property} annotation.

+ */ + protected void processAnnotation(final Object bean) { + + final Class clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + //Annotation annotation = method.getAnnotation(getPropertyAnnotationType()); + Property annotation = (Property) method.getAnnotation(getPropertyAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on static methods"); + } + + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on private methods"); + } + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException("Property annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + if (pd != null) { + String propName = annotation.name(); + if ("".equals(propName)) { + injectProperty(bean, pd, getPropertyObj(pd.getPropertyType(), pd.getName())); + } else { + injectProperty(bean, pd, getPropertyObj(pd.getPropertyType(), propName)); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + //Annotation annotation = field.getAnnotation(getPropertyAnnotationType()); + Property annotation = (Property) field.getAnnotation(getPropertyAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on static fields"); + } + + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("Property annotation is not supported on private fields"); + } + + ReflectionUtils.makeAccessible(field); + + Object propertyObj = null; + String propName = annotation.name(); + if ("".equals(propName)) { + propertyObj = getPropertyObj(field.getType(), field.getName()); + } else { + propertyObj = getPropertyObj(field.getType(), propName); + } + + if (propertyObj != null) + ReflectionUtils.setField(field, bean, propertyObj); + } + } + }); + } + + /** + * Processes a property descriptor to inject a service. + */ + public Object getPropertyObj(Class requiredType, String name) { + + Object propertyObj = null; + + List props = component.getProperties(); + for (ComponentProperty prop : props) { + if (prop.getName().equals(name)) { + // On finding the property, create a factory for it and create a Bean using + // the factory + ObjectFactory factory = propertyFactory.createValueFactory(prop, prop.getValue(), requiredType); + propertyObj = factory.getInstance(); + } // end if + } // end for + + return propertyObj; + } + + + public void injectProperty(Object bean, PropertyDescriptor pd, Object propertyObj) { + + if (propertyObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] { propertyObj }); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting property: " + e.getMessage(), e); + } + } + } + + /** + * Processes a property descriptor to inject a service. + */ + /*public void injectMethod(Object bean, Method method) { + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + + if (pd != null) { + Object propertyObj = null; + + List props = component.getProperties(); + for (ComponentProperty prop : props) { + if (prop.getName().equals(pd.getName())) { + // On finding the property, create a factory for it and create a Bean using + // the factory + ObjectFactory factory = propertyFactory.createValueFactory(prop, prop.getValue(), pd.getPropertyType()); + propertyObj = factory.getInstance(); + } // end if + } // end for + + if (propertyObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] { propertyObj }); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting property: " + e.getMessage(), e); + } + } + } + }*/ +} diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java new file mode 100644 index 0000000000..52f8ac3684 --- /dev/null +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java @@ -0,0 +1,186 @@ +/* + * 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.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; + +import org.springframework.util.Assert; +import org.springframework.beans.BeanUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; + +import org.osoa.sca.annotations.Reference; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +public class ReferenceAnnotationProcessor implements BeanPostProcessor { + + private Class referenceAnnotationType = Reference.class; + + private RuntimeComponent component; + + public ReferenceAnnotationProcessor (RuntimeComponent component) { + this.component = component; + } + + /** + * Gets referece annotation type. + */ + protected Class getReferenceAnnotationType() { + return this.referenceAnnotationType; + } + + /** + * Sets referece annotation type. + */ + public void setReferenceAnnotationType(Class referenceAnnotationType) { + Assert.notNull(referenceAnnotationType, "'referenceAnnotationType' type must not be null."); + this.referenceAnnotationType = referenceAnnotationType; + } + + /** + * This method is used to execute before a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + processAnnotation(bean); + return bean; + } + + /** + * This method is used to execute after a bean's initialization callback. + * + * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String) + */ + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + /** + *

Processes a beans fields for injection if it has a {@link Reference} annotation.

+ */ + protected void processAnnotation(final Object bean) { + + final Class clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + //Annotation annotation = method.getAnnotation(getReferenceAnnotationType()); + Reference annotation = (Reference) method.getAnnotation(getReferenceAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on static methods"); + } + + if (Modifier.isPrivate(method.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on private methods"); + } + + if (method.getParameterTypes().length == 0) { + throw new IllegalStateException("Reference annotation requires at least one argument: " + method); + } + + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + if (pd != null) { + String refName = annotation.name(); + if ("".equals(refName)) { + injectReference(bean, pd, pd.getName()); + } else { + injectReference(bean, pd, refName); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + //Annotation annotation = field.getAnnotation(getReferenceAnnotationType()); + Reference annotation = (Reference) field.getAnnotation(getReferenceAnnotationType()); + + if (annotation != null) { + if (Modifier.isStatic(field.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on static fields"); + } + + if (Modifier.isPrivate(field.getModifiers())) { + throw new IllegalStateException("Reference annotation is not supported on private fields"); + } + + ReflectionUtils.makeAccessible(field); + + Object referenceObj = null; + String refName = annotation.name(); + if ("".equals(refName)) { + referenceObj = component.getComponentContext().getService(field.getType(), field.getName()); + } else { + referenceObj = component.getComponentContext().getService(field.getType(), refName); + } + + if (referenceObj != null) + ReflectionUtils.setField(field, bean, referenceObj); + } + } + }); + } + + /** + * Processes a property descriptor to inject a service. + */ + public void injectReference(Object bean, PropertyDescriptor pd, String name) { + + Object referenceObj = component.getComponentContext().getService(pd.getPropertyType(), name); + + if (referenceObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] { referenceObj }); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } + + /** + * Processes a property descriptor to inject a service. + */ + /*public void injectMethod(Object bean, Method method) { + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); + + if (pd != null) { + Object referenceObj = component.getComponentContext().getService(pd.getPropertyType(), pd.getName()); + + if (referenceObj != null) { + try { + pd.getWriteMethod().invoke(bean, new Object[] { referenceObj }); + } catch (Throwable e) { + throw new FatalBeanException("Problem injecting reference: " + e.getMessage(), e); + } + } + } + }*/ +} diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java index 625a46b12b..3e526cd20e 100644 --- a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java @@ -47,6 +47,7 @@ import org.apache.tuscany.sca.implementation.java.introspect.impl.ScopeProcessor 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; +import org.apache.tuscany.sca.implementation.spring.SpringImplementation; /** * Provides introspection functions for Spring beans @@ -106,9 +107,9 @@ public class SpringBeanIntrospector { * Spring Bean or its componentType * */ - public Map introspectBean(Class beanClass, ComponentType componentType) - throws ContributionResolveException { - + public Map introspectBean(Class beanClass, ComponentType componentType, + SpringImplementation springImplementation) throws ContributionResolveException + { if (componentType == null) throw new ContributionResolveException("Introspect Spring bean: supplied componentType is null"); @@ -124,6 +125,11 @@ public class SpringBeanIntrospector { componentType.getServices().addAll(javaImplementation.getServices()); componentType.getReferences().addAll(javaImplementation.getReferences()); componentType.getProperties().addAll(javaImplementation.getProperties()); + + springImplementation.setInitMethod(javaImplementation.getInitMethod()); + springImplementation.setDestroyMethod(javaImplementation.getDestroyMethod()); + springImplementation.setConstructor(javaImplementation.getConstructor()); + } catch (IntrospectionException e) { throw new ContributionResolveException(e); } // end try diff --git a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java index 9f41fd306f..34f46dacb9 100644 --- a/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java +++ b/java/sca/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java @@ -336,7 +336,7 @@ public class SpringXMLComponentTypeLoader { Class beanClass = cl.loadClass(beanElement.getClassName()); // Introspect the bean ComponentType beanComponentType = assemblyFactory.createComponentType(); - beanIntrospector.introspectBean(beanClass, beanComponentType); + beanIntrospector.introspectBean(beanClass, beanComponentType, implementation); // Get the service interface defined by this Spring Bean and add to // the component type of the Spring Assembly List beanServices = beanComponentType.getServices(); @@ -368,7 +368,7 @@ public class SpringXMLComponentTypeLoader { // Introspect the bean ComponentType beanComponentType = assemblyFactory.createComponentType(); Map propertyMap = - beanIntrospector.introspectBean(beanClass, beanComponentType); + beanIntrospector.introspectBean(beanClass, beanComponentType, implementation); // Get the references by this Spring Bean and add the unresolved ones to // the component type of the Spring Assembly List beanReferences = beanComponentType.getReferences(); -- cgit v1.2.3