diff options
Diffstat (limited to 'sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org')
16 files changed, 1483 insertions, 0 deletions
diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/SCANamespaceHandlerResolver.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/SCANamespaceHandlerResolver.java new file mode 100644 index 0000000000..75e00007f6 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/SCANamespaceHandlerResolver.java @@ -0,0 +1,53 @@ +/* + * 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.namespace; + +import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver; +import org.springframework.beans.factory.xml.NamespaceHandler; + +/** + * Overrides the default Spring namespace resolver to automatically register + * {@link ScaNamespaceHandler} instead of requiring a value to be supplied in a + * Spring configuration + * + * @version $Rev$ $Date$ + */ +public class SCANamespaceHandlerResolver extends DefaultNamespaceHandlerResolver { + private static final String SCA_NAMESPACE = "http://www.springframework.org/schema/sca"; + + private ScaNamespaceHandler handler; + + public SCANamespaceHandlerResolver(ClassLoader classLoader) { + super(classLoader); + handler = new ScaNamespaceHandler(/*componentType*/); + } + + public SCANamespaceHandlerResolver(String handlerMappingsLocation, ClassLoader classLoader) { + super(classLoader, handlerMappingsLocation); + handler = new ScaNamespaceHandler(/*componentType*/); + } + + @Override + public NamespaceHandler resolve(String namespaceUri) { + if (SCA_NAMESPACE.equals(namespaceUri)) { + return handler; + } + return super.resolve(namespaceUri); + } +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaNamespaceHandler.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaNamespaceHandler.java new file mode 100644 index 0000000000..f136e45b87 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaNamespaceHandler.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.namespace; + +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +/** + * Handler for the <sca:> namespace in an application context + * + * @version $Rev$ $Date$ + */ +public class ScaNamespaceHandler extends NamespaceHandlerSupport { + + public ScaNamespaceHandler() { + init(); + } + + public final void init() { + registerBeanDefinitionParser("reference", new ScaReferenceBeanDefinitionParser()); + registerBeanDefinitionParser("service", new ScaServiceBeanDefinitionParser()); + registerBeanDefinitionParser("property", new ScaPropertyBeanDefinitionParser()); + } + +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaPropertyBeanDefinitionParser.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaPropertyBeanDefinitionParser.java new file mode 100644 index 0000000000..5b1064d8d8 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaPropertyBeanDefinitionParser.java @@ -0,0 +1,35 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.namespace; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:reference> element + * @version $Rev$ $Date$ + */ +public class ScaPropertyBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + // do nothing, this is handled by Tuscany + return null; + } + +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaReferenceBeanDefinitionParser.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaReferenceBeanDefinitionParser.java new file mode 100644 index 0000000000..fac02760c9 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaReferenceBeanDefinitionParser.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.namespace; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:reference> element + * + * @version $Rev$ $Date$ + */ +public class ScaReferenceBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + // do nothing, this is handled by Tuscany + return null; + } + +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaServiceBeanDefinitionParser.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaServiceBeanDefinitionParser.java new file mode 100644 index 0000000000..3020dca8bc --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/namespace/ScaServiceBeanDefinitionParser.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed 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.namespace; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.w3c.dom.Element; + +/** + * Parser for the <sca:service/> element + * + * @version $Rev$ $Date$ + */ +public class ScaServiceBeanDefinitionParser implements BeanDefinitionParser { + + public BeanDefinition parse(Element element, ParserContext parserContext) { + // do nothing, handled by Tuscany + return null; + } + +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java new file mode 100644 index 0000000000..7613f8166d --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentNameAnnotationProcessor.java @@ -0,0 +1,150 @@ +/* + * 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.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.ref.Reference; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.ComponentName; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class ComponentNameAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> componentNameAnnotationType = ComponentName.class; + + private String componentName; + + public ComponentNameAnnotationProcessor (String componentName) { + this.componentName = componentName; + } + + /** + * Gets componentName annotation type. + */ + protected Class<? extends Annotation> getComponentNameAnnotationType() { + return this.componentNameAnnotationType; + } + + /** + * Sets componentName annotation type. + */ + public void setComponentNameAnnotationType(Class<? extends Annotation> 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; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Reference} annotation.</p> + */ + 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 = componentName; + 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 = componentName; + 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/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentStub.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentStub.java new file mode 100644 index 0000000000..c72ccd6636 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ComponentStub.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.processor; + +import java.lang.reflect.Method; + +/** + * This is the Spring runtime side stub for the corresponding Tuscany tie class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the ComponentTie class + * in the implementation-spring module for what the tie does. + */ +public class ComponentStub { + + private Object tie; + private Method getService; + + public ComponentStub(Object tie) { + this.tie = tie; + Class<?> tieClass = tie.getClass(); + try { + getService = tieClass.getMethod("getService", new Class<?>[]{Class.class, String.class}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getService(Class<?> type, String name) { + try { + + return getService.invoke(tie, type, name); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java new file mode 100644 index 0000000000..7eb63678f6 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ConstructorAnnotationProcessor.java @@ -0,0 +1,115 @@ +/* + * 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 java.lang.reflect.Constructor; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.util.Assert; + +public class ConstructorAnnotationProcessor extends InstantiationAwareBeanPostProcessorAdapter { + + private Class<? extends Annotation> constructorAnnotationType + = org.oasisopen.sca.annotation.Constructor.class; + + private Class<? extends Annotation> 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<? extends Annotation> autowiredAnnotationType) { + Assert.notNull(autowiredAnnotationType, "'autowiredAnnotationType' must not be null"); + this.autowiredAnnotationType = autowiredAnnotationType; + } + + /** + * Return the 'autowired' annotation type. + */ + protected Class<? extends Annotation> getAutowiredAnnotationType() { + return this.autowiredAnnotationType; + } + + /** + * Return the 'constructor' annotation type. + */ + protected Class<? extends Annotation> getConstructorAnnotationType() { + return this.constructorAnnotationType; + } + + /** + * Sets the 'constructor' annotation type. + */ + public void setConstructorAnnotationType(Class<? extends Annotation> 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/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java new file mode 100644 index 0000000000..477582b1d3 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/InitDestroyAnnotationProcessor.java @@ -0,0 +1,75 @@ +/* + * 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.oasisopen.sca.annotation.Destroy; +import org.oasisopen.sca.annotation.Init; +import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor; + +public class InitDestroyAnnotationProcessor extends InitDestroyAnnotationBeanPostProcessor { + + private static final long serialVersionUID = 0; + + private Class<? extends Annotation> initAnnotationType = Init.class; + private Class<? extends Annotation> destroyAnnotationType = Destroy.class; + + /** + * Gets init annotation type. + */ + protected Class<? extends Annotation> getInitAnnotationType() { + return this.initAnnotationType; + } + + /** + * Sets init annotation type. + */ + /* + * public void setInitAnnotationType(Class<? extends Annotation> + * initAnnotationType) { Assert.notNull(initAnnotationType, + * "Init annotation type must not be null."); this.initAnnotationType = + * initAnnotationType; } + */ + + /** + * Gets destroy annotation type. + */ + protected Class<? extends Annotation> getDestroyAnnotationType() { + return this.destroyAnnotationType; + } + + /** + * Sets destroy annotation type. + */ + /* + * public void setDestroyAnnotationType(Class<? extends Annotation> + * 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/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java new file mode 100644 index 0000000000..f800654c34 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyAnnotationProcessor.java @@ -0,0 +1,161 @@ +/* + * 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.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.Property; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class PropertyAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> propertyAnnotationType = Property.class; + + private PropertyValueStub propertyValue; + + public PropertyAnnotationProcessor (PropertyValueStub propertyValue) { + this.propertyValue = propertyValue; + } + + /** + * Gets property annotation type. + */ + protected Class<? extends Annotation> getPropertyAnnotationType() { + return this.propertyAnnotationType; + } + + /** + * Sets property annotation type. + */ + public void setPropertyAnnotationType(Class<? extends Annotation> 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; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Property} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + + 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, propertyValue.getPropertyObj(pd.getPropertyType(), pd.getName())); + } else { + injectProperty(bean, pd, propertyValue.getPropertyObj(pd.getPropertyType(), propName)); + } + } + } + } + }); + + ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() { + public void doWith(Field field) { + + 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 = propertyValue.getPropertyObj(field.getType(), field.getName()); + } else { + propertyObj = propertyValue.getPropertyObj(field.getType(), propName); + } + + if (propertyObj != null) + ReflectionUtils.setField(field, bean, 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); + } + } + } + +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyValueStub.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyValueStub.java new file mode 100644 index 0000000000..ea8f560ae1 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/PropertyValueStub.java @@ -0,0 +1,55 @@ +/* + * 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; + +/** + * This is the Spring runtime side stub for the corresponding Tuscany tie class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the PropertyValueTie class + * in the implementation-spring module for what the tie does. + */ +public class PropertyValueStub { + + private Object tie; + private Method getPropertyObj; + + public PropertyValueStub(Object tie) { + this.tie = tie; + Class<?> tieClass = tie.getClass(); + try { + getPropertyObj = tieClass.getMethod("getPropertyObj", new Class<?>[]{Class.class, String.class}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getPropertyObj(Class<?> propertyType, String name) { + try { + + return getPropertyObj.invoke(tie, propertyType, name); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java new file mode 100644 index 0000000000..dd43d63d97 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/processor/ReferenceAnnotationProcessor.java @@ -0,0 +1,164 @@ +/* + * 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.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.oasisopen.sca.annotation.Reference; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.util.Assert; +import org.springframework.util.ReflectionUtils; + +public class ReferenceAnnotationProcessor implements BeanPostProcessor { + + private Class<? extends Annotation> referenceAnnotationType = Reference.class; + private ComponentStub component; + + public ReferenceAnnotationProcessor (ComponentStub component) { + this.component = component; + } + + /** + * Gets referece annotation type. + */ + protected Class<? extends Annotation> getReferenceAnnotationType() { + return this.referenceAnnotationType; + } + + /** + * Sets referece annotation type. + */ + public void setReferenceAnnotationType(Class<? extends Annotation> 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; + } + + /** + * <p>Processes a beans fields for injection if it has a {@link Reference} annotation.</p> + */ + protected void processAnnotation(final Object bean) { + + final Class<?> clazz = bean.getClass(); + + ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { + public void doWith(Method method) { + + 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) { + + 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.getService(field.getType(), field.getName()); + } else { + referenceObj = component.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.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); + } + } + } +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SCAGenericApplicationContext.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SCAGenericApplicationContext.java new file mode 100644 index 0000000000..6426306f26 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SCAGenericApplicationContext.java @@ -0,0 +1,47 @@ +/* + * 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.runtime.context; + +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; + +public class SCAGenericApplicationContext extends GenericApplicationContext { + + ClassLoader classloader = null; + + public SCAGenericApplicationContext(DefaultListableBeanFactory beanFactory, + ApplicationContext parent, + ClassLoader classloader) { + super(beanFactory, parent); + this.classloader = classloader; + } + + public SCAGenericApplicationContext(ApplicationContext parent, + ClassLoader classloader) { + super(parent); + this.classloader = classloader; + } + + @Override + protected void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) { + beanFactory.setBeanClassLoader(classloader); + } +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SCAParentApplicationContext.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SCAParentApplicationContext.java new file mode 100644 index 0000000000..36f1f6d761 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SCAParentApplicationContext.java @@ -0,0 +1,202 @@ +/* + * 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.runtime.context; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Locale; +import java.util.Map; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.NoSuchMessageException; +import org.springframework.core.io.Resource; + +/** + * A Spring ParentApplicationContext for a given Spring Implementation + * + * The Parent application context is responsible for handling those entities within a Spring + * application context that actually belong to SCA rather than to Spring. The principal things + * are Properties and References. These may be present either through explicit <sca:property/> + * and <sca:reference/> elements in the application context or they may be implicit through + * unresolved Spring bean <property.../> elements. In either case, it is the Parent application + * context that must provide Spring beans that correspond to the property or reference, as derived + * from the SCA composite in which the Spring application context is an implementation. + * + * @version $Rev$ $Date$ + */ +class SCAParentApplicationContext implements ApplicationContext { + + // The Spring implementation for which this is the parent application context + private SpringImplementationStub implementation; + + private static final String[] EMPTY_ARRAY = new String[0]; + + public SCAParentApplicationContext(SpringImplementationStub implementation) { + this.implementation = implementation; + } // end constructor + + public Object getBean(String name) throws BeansException { + return getBean(name, (Class) null); + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class requiredType) throws BeansException { + return implementation.getBean(name, requiredType); + } // end method getBean( String, Class ) + + public Object getBean(String name, Object[] args) throws BeansException { + return getBean(name, ((Class)null)); + } + + public <T> T getBean(Class<T> clazz) throws BeansException { + return clazz.cast(implementation.getBean(clazz.getName(), clazz)); + } + + public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> clazz) throws BeansException { + return null; + } + + public <A extends Annotation> A findAnnotationOnBean(String arg0, Class<A> clazz) { + return null; + } + + public boolean containsBean(String name) { + // TODO + return false; + } + + public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + // TODO + return false; + } + + public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException { + throw new UnsupportedOperationException(); + } + + public Class getType(String name) throws NoSuchBeanDefinitionException { + return null; + } + + public String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return EMPTY_ARRAY; + } + + public ApplicationContext getParent() { + return null; + } + + public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException { + return null; + } + + public String getId() { + return this.toString(); + } + + public String getDisplayName() { + return implementation.getURI(); + } + + public long getStartupDate() { + return 0; + } + + public boolean containsBeanDefinition(String beanName) { + return false; + } + + public int getBeanDefinitionCount() { + return 0; + } + + public String[] getBeanDefinitionNames() { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type) { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans) { + return new String[0]; + } + + public Map getBeansOfType(Class type) throws BeansException { + return null; + } + + public Map getBeansOfType(Class type, boolean includePrototypes, boolean includeFactoryBeans) throws BeansException { + return null; + } + + public boolean isPrototype(String theString) { + return false; + } + + public BeanFactory getParentBeanFactory() { + return null; + } + + public boolean containsLocalBean(String name) { + return false; + } + + public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { + return null; + } + + public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException { + return null; + } + + public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { + return null; + } + + public void publishEvent(ApplicationEvent event) { + + } + + public Resource[] getResources(String locationPattern) throws IOException { + return new Resource[0]; + } + + public Resource getResource(String location) { + return null; + } + + public ClassLoader getClassLoader() { + // REVIEW: this is almost certainly flawed, but it's not clear how the SCA runtime's + // resource loading mechanism is exposed right now. + return this.getClass().getClassLoader(); + } +} diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SpringContextTie.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SpringContextTie.java new file mode 100644 index 0000000000..77681b600f --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SpringContextTie.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.runtime.context; + +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.implementation.spring.processor.ComponentNameAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.ComponentStub; +import org.apache.tuscany.sca.implementation.spring.processor.ConstructorAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.InitDestroyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.PropertyAnnotationProcessor; +import org.apache.tuscany.sca.implementation.spring.processor.PropertyValueStub; +import org.apache.tuscany.sca.implementation.spring.processor.ReferenceAnnotationProcessor; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.UrlResource; + +/** + * This is the runtime side tie for the corresponding tuscany side stub class. + * It enables the Tuscany code to invoke methods on a Spring context without + * needing to know about any Spring classes. See the SpringContextStub class + * in the implementation-spring module for what the stub does. + */ +public class SpringContextTie { + + private AbstractApplicationContext springContext; + private SpringImplementationStub implementation; + + public SpringContextTie(SpringImplementationStub implementation, List<URL> resource) { + this.implementation = implementation; + SCAParentApplicationContext scaParentContext = new SCAParentApplicationContext(implementation); + springContext = createApplicationContext(scaParentContext, resource); + } + + public void start() { + // Do refresh here to ensure that Spring Beans are not touched before the SCA config process is complete... + springContext.refresh(); + springContext.start(); + } + + public void close() { + springContext.close(); + if (springContext instanceof GenericApplicationContext) { + springContext.stop(); + } + } + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private AbstractApplicationContext createApplicationContext(SCAParentApplicationContext scaParentContext, List<URL> resources) { + + XmlBeanFactory beanFactory = null; + AbstractApplicationContext appContext = null; + + if (resources.size() > 1) { + GenericApplicationContext appCtx = + new SCAGenericApplicationContext(scaParentContext, implementation.getClassLoader()); + XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appCtx); + for (URL resource : resources) { + xmlReader.loadBeanDefinitions(new UrlResource(resource)); + } + xmlReader.setBeanClassLoader(implementation.getClassLoader()); + includeAnnotationProcessors(appCtx.getBeanFactory()); + return appCtx; + } + + // use the generic application context as default + beanFactory = new XmlBeanFactory(new UrlResource(resources.get(0))); + beanFactory.setBeanClassLoader(implementation.getClassLoader()); + includeAnnotationProcessors(beanFactory); + appContext = new SCAGenericApplicationContext(beanFactory, + scaParentContext, + implementation.getClassLoader()); + return appContext; + } + + public Object getBean(String id) throws BeansException { + return springContext.getBean(id); + } + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private void includeAnnotationProcessors(ConfigurableListableBeanFactory beanFactory) { + + // Processor to deal with @Init and @Destroy SCA Annotations + BeanPostProcessor initDestroyProcessor = new InitDestroyAnnotationProcessor(); + beanFactory.addBeanPostProcessor(initDestroyProcessor); + + // Processor to deal with @Reference SCA Annotations + ComponentStub component = new ComponentStub(implementation.getComponentTie()); + BeanPostProcessor referenceProcessor = new ReferenceAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(referenceProcessor); + + // Processor to deal with @Property SCA Annotations + PropertyValueStub pvs = new PropertyValueStub(implementation.getPropertyValueTie()); + BeanPostProcessor propertyProcessor = new PropertyAnnotationProcessor(pvs); + beanFactory.addBeanPostProcessor(propertyProcessor); + + // Processor to deal with @ComponentName SCA Annotations + BeanPostProcessor componentNameProcessor = new ComponentNameAnnotationProcessor(implementation.getComponentName()); + beanFactory.addBeanPostProcessor(componentNameProcessor); + + // Processor to deal with @Constructor SCA Annotations + BeanPostProcessor constructorProcessor = new ConstructorAnnotationProcessor(); + beanFactory.addBeanPostProcessor(constructorProcessor); + } + +}
\ No newline at end of file diff --git a/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SpringImplementationStub.java b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SpringImplementationStub.java new file mode 100644 index 0000000000..af39869522 --- /dev/null +++ b/sca-java-2.x/trunk/modules/implementation-spring-runtime/src/main/java/org/apache/tuscany/sca/implementation/spring/runtime/context/SpringImplementationStub.java @@ -0,0 +1,129 @@ +/* + * 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.runtime.context; + +import java.lang.reflect.Method; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; + +/** + * This is the runtime side stub for the corresponding Tuscany-side stub class. + * It enables the Spring code in the runtime module to invoke methods on a + * Tuscany SpringImplementation without the Spring runtime module + * needing to know about any Tuscany classes. See the SpringImplementationTie class + * in the implementation-spring module for what the tie does. + */ +public class SpringImplementationStub { + + Object tie; + Method getURI; + Method getBean; + Method getComponentName; + Method getComponentTie; + Method getPropertyValueTie; + Method getClassLoader; + + public SpringImplementationStub(Object tie) { + this.tie = tie; + Class<?> tieClass = tie.getClass(); + try { + getURI = tieClass.getMethod("getURI", new Class<?>[]{}); + getBean = tieClass.getMethod("getBean", new Class<?>[]{String.class, Class.class}); + getComponentName = tieClass.getMethod("getComponentName"); + getComponentTie = tieClass.getMethod("getComponentTie"); + getPropertyValueTie = tieClass.getMethod("getPropertyValueTie"); + getClassLoader = tieClass.getMethod("getClassLoader"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String getURI() { + try { + + return (String)getURI.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Get a Bean for a reference or for a property. + * + * @param name - the name of the Bean required + * @param requiredType - the required type of the Bean (either a Java class or a Java interface) + * @return Object - a Bean which matches the requested bean + */ + public Object getBean(String name, Class<?> requiredType) throws BeansException { + try { + + Object bean = getBean.invoke(tie, new Object[] {name, requiredType}); + if (bean == null) { + throw new NoSuchBeanDefinitionException("Unable to find Bean with name " + name); + } + return bean; + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public String getComponentName() { + try { + + return (String)getComponentName.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getComponentTie() { + try { + + return getComponentTie.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Object getPropertyValueTie() { + try { + + return getPropertyValueTie.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public ClassLoader getClassLoader() { + try { + + return (ClassLoader) getClassLoader.invoke(tie); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +}
\ No newline at end of file |