From bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a Mon Sep 17 00:00:00 2001 From: dims Date: Tue, 17 Jun 2008 00:23:01 +0000 Subject: Move Tuscany from Incubator to top level. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68 --- .../osgi/context/OSGiAnnotations.java | 316 +++++++++++++++++++++ .../osgi/context/OSGiPropertyInjector.java | 289 +++++++++++++++++++ .../context/OSGiPropertyValueObjectFactory.java | 225 +++++++++++++++ 3 files changed, 830 insertions(+) create mode 100644 branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiAnnotations.java create mode 100644 branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyInjector.java create mode 100644 branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java (limited to 'branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context') diff --git a/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiAnnotations.java b/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiAnnotations.java new file mode 100644 index 0000000000..b118cc7677 --- /dev/null +++ b/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiAnnotations.java @@ -0,0 +1,316 @@ +/* + * 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.osgi.context; + + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Hashtable; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.AllowsPassByReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ComponentNameProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConstructorProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ContextProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConversationProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.DestroyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.EagerInitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.InitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PolicyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PropertyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ResourceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ServiceProcessor; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.osgi.framework.Bundle; + + +/** + * OSGi annotation processing + * OSGi bundles are not introspected by OSGiImplementation when a component is created. + * Instead if the list of implementation classes is specified in , + * the classes are introspected when the bundle is resolved. The classes are loaded using + * the bundle classloader, and hence the delay in annotation processing is inevitable. + * There is one other difference compared to implementation.java. While instances (and + * the instance class) are associated with a component in Java, all Java annotations from + * the component implementation class apply to all the component instances. In OSGi, + * instances are associated with services, and a bundle can register multiple services. + * Hence annotations from classes need to be stored separately so that the right ones + * can be associated with the service instance. + */ +public class OSGiAnnotations { + + private Scope scope = Scope.COMPOSITE; + private boolean isEagerInit; + + private String[] classList; + + private Bundle[] bundles; + + private RuntimeComponent runtimeComponent; + private JavaPropertyValueObjectFactory propertyValueFactory; + private ProxyFactory proxyFactory; + + private JavaImplementationFactory javaImplementationFactory; + private JavaInterfaceFactory javaInterfaceFactory; + private PolicyFactory policyFactory; + private RequestContextFactory requestContextFactory; + + private Hashtable, JavaImplementation> javaAnnotationInfo = + new Hashtable, JavaImplementation>(); + private Hashtable propertyInjectors = + new Hashtable(); + + private long maxAge = Long.MAX_VALUE; + private long maxIdleTime = Long.MAX_VALUE; + + private boolean annotationsProcessed; + + + + public OSGiAnnotations(ModelFactoryExtensionPoint modelFactories, + String[] classList, + RuntimeComponent runtimeComponent, + JavaPropertyValueObjectFactory propertyValueFactory, + ProxyFactory proxyFactory, + RequestContextFactory requestContextFactory, + Bundle mainBundle, + ArrayList dependentBundles) { + + + this.classList = classList; + this.runtimeComponent = runtimeComponent; + this.propertyValueFactory = propertyValueFactory; + this.proxyFactory = proxyFactory; + + AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + this.javaInterfaceFactory = modelFactories.getFactory(JavaInterfaceFactory.class); + this.javaImplementationFactory = createJavaImplementationFactory(assemblyFactory); + this.policyFactory = modelFactories.getFactory(PolicyFactory.class); + + bundles = new Bundle[dependentBundles.size() + 1]; + bundles[0] = mainBundle; + for (int i = 0; i < dependentBundles.size(); i++) + bundles[i + 1] = dependentBundles.get(i); + + } + + + public void processAnnotations() throws IntrospectionException { + + if (annotationsProcessed) + return; + annotationsProcessed = true; + for (String className : classList) { + for (Bundle bundle : bundles) { + try { + Class clazz = bundle.loadClass(className); + + processAnnotations(clazz); + + break; + + } catch (ClassNotFoundException e) { + } + } + } + } + + + public void injectProperties(Object instance) { + JavaImplementation javaImpl = getAnnotationInfo(instance); + if (javaImpl != null) { + OSGiPropertyInjector injector = propertyInjectors.get(javaImpl); + if (injector != null) + injector.injectProperties(instance); + } + } + + + public Scope getScope() { + return scope; + } + + + + public boolean isAllowsPassByReference(Object instance, Method method) { + + JavaImplementation javaImpl = getAnnotationInfo(instance); + if (javaImpl == null) { + return false; + } + if (javaImpl.isAllowsPassByReference()) { + return true; + } + return javaImpl.isAllowsPassByReference(method); + } + + + public boolean isEagerInit() { + return isEagerInit; + } + + public long getMaxAge() { + return maxAge; + } + + public long getMaxIdleTime() { + return maxIdleTime; + } + + public Method getInitMethod(Object instance) { + JavaImplementation javaImpl = getAnnotationInfo(instance); + return javaImpl == null? null : javaImpl.getInitMethod(); + } + + + public Method getDestroyMethod(Object instance) { + JavaImplementation javaImpl = getAnnotationInfo(instance); + return javaImpl == null? null : javaImpl.getDestroyMethod(); + } + + + /* + * Get the annotation corresponding to an instance + * + */ + private JavaImplementation getAnnotationInfo(Object instance) { + + // The simplest case where the implementation class was listed under the + // classes attribute of , or this is the second call + // to this method for the implementation class. + JavaImplementation javaImpl = javaAnnotationInfo.get(instance.getClass()); + if (javaImpl != null) + return javaImpl; + + // Process annotations from the instance class. + try { + return processAnnotations(instance.getClass()); + } catch (IntrospectionException e) { + // e.printStackTrace(); + } + + return null; + } + + + private JavaImplementation processAnnotations(Class clazz) + throws IntrospectionException { + + JavaImplementation javaImpl = javaImplementationFactory.createJavaImplementation(clazz); + + javaAnnotationInfo.put(clazz, javaImpl); + + OSGiPropertyInjector propertyInjector = new OSGiPropertyInjector( + javaImpl, runtimeComponent, propertyValueFactory, proxyFactory, requestContextFactory); + + propertyInjectors.put(javaImpl, propertyInjector); + + if (javaImpl.isEagerInit()) + isEagerInit = true; + if (javaImpl.getMaxAge() != Long.MAX_VALUE) + maxAge = javaImpl.getMaxAge(); + if (javaImpl.getMaxIdleTime() != Long.MAX_VALUE) + maxIdleTime = javaImpl.getMaxIdleTime(); + if (javaImpl.getJavaScope() != JavaScopeImpl.COMPOSITE) + scope = new Scope(javaImpl.getJavaScope().getScope()); + + return javaImpl; + } + + + + + private JavaImplementationFactory createJavaImplementationFactory(AssemblyFactory assemblyFactory) { + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + // Create the list of class visitors + BaseJavaClassVisitor[] extensions = + new BaseJavaClassVisitor[] { + new ConstructorProcessor(assemblyFactory), + new AllowsPassByReferenceProcessor(assemblyFactory), + new ComponentNameProcessor(assemblyFactory), + new ContextProcessor(assemblyFactory), + new ConversationProcessor(assemblyFactory), + new DestroyProcessor(assemblyFactory), + new EagerInitProcessor(assemblyFactory), + new InitProcessor(assemblyFactory), + new PropertyProcessor(assemblyFactory), + new ReferenceProcessor(assemblyFactory, javaInterfaceFactory), + new ResourceProcessor(assemblyFactory), + new OSGiScopeProcessor(assemblyFactory), + new ServiceProcessor(assemblyFactory, javaInterfaceFactory), + new HeuristicPojoProcessor(assemblyFactory, javaInterfaceFactory), + new PolicyProcessor(assemblyFactory, policyFactory)}; + for (JavaClassVisitor extension : extensions) { + javaImplementationFactory.addClassVisitor(extension); + } + + return javaImplementationFactory; + } + + private class OSGiScopeProcessor extends BaseJavaClassVisitor { + + public OSGiScopeProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitClass(Class clazz, + JavaImplementation type) + throws IntrospectionException { + org.osoa.sca.annotations.Scope annotation = clazz.getAnnotation(org.osoa.sca.annotations.Scope.class); + if (annotation == null) { + type.setJavaScope(JavaScopeImpl.COMPOSITE); + return; + } + String name = annotation.value(); + JavaScopeImpl scope; + if ("COMPOSITE".equals(name)) { + scope = JavaScopeImpl.COMPOSITE; + } else if ("SESSION".equals(name)) { + scope = JavaScopeImpl.SESSION; + } else if ("CONVERSATION".equals(name)) { + scope = JavaScopeImpl.CONVERSATION; + } else if ("REQUEST".equals(name)) { + scope = JavaScopeImpl.REQUEST; + } else { + scope = new JavaScopeImpl(name); + } + type.setJavaScope(scope); + } + } + + +} diff --git a/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyInjector.java b/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyInjector.java new file mode 100644 index 0000000000..cff2c86478 --- /dev/null +++ b/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyInjector.java @@ -0,0 +1,289 @@ +/* + * 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.osgi.context; + + +import java.lang.annotation.ElementType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.context.RequestContextImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.ConversationIDObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.FieldInjector; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.injection.InvalidAccessorException; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.MethodInjector; +import org.apache.tuscany.sca.implementation.java.injection.ResourceObjectFactory; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.annotations.ConversationID; + + +/** + * OSGi property injection support + */ +public class OSGiPropertyInjector { + + + private ArrayList injectionSites = new ArrayList(); + private Hashtable factories = + new Hashtable(); + + private Injector[] injectors; + + public OSGiPropertyInjector( + JavaImplementation javaImpl, + RuntimeComponent component, + JavaPropertyValueObjectFactory propertyValueFactory, + ProxyFactory proxyFactory, + RequestContextFactory requestContextFactory) throws IntrospectionException { + + createInjectionSites(javaImpl, component, propertyValueFactory, proxyFactory, requestContextFactory); + + injectors = createInjectors(); + + } + + + @SuppressWarnings("unchecked") + public void injectProperties(Object instance) { + + for (Injector injector : injectors) { + injector.inject(instance); + } + + } + + + @SuppressWarnings("unchecked") + private void createInjectionSites( + JavaImplementation javaImpl, + RuntimeComponent component, + JavaPropertyValueObjectFactory propertyValueFactory, + ProxyFactory proxyFactory, + RequestContextFactory requestContextFactory) + { + + List componentProperties = component.getProperties(); + Map propertyMembers = javaImpl.getPropertyMembers(); + + for (ComponentProperty prop : componentProperties) { + JavaElementImpl element = propertyMembers.get(prop.getName()); + + if (element != null && !(element.getAnchor() instanceof Constructor) && prop.getValue() != null) { + Class propertyJavaType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + ObjectFactory objFactory = propertyValueFactory.createValueFactory(prop, prop.getValue(), propertyJavaType); + + factories.put(element, objFactory); + injectionSites.add(element); + } + } + + for (Member member : javaImpl.getConversationIDMembers()) { + ObjectFactory factory = new ConversationIDObjectFactory(); + if (member instanceof Field) { + JavaElementImpl element = new JavaElementImpl((Field) member); + element.setClassifer(ConversationID.class); + injectionSites.add(element); + factories.put(element, factory); + } else if (member instanceof Method) { + JavaElementImpl element = new JavaElementImpl((Method) member, 0); + element.setName(JavaIntrospectionHelper.toPropertyName(member.getName())); + element.setClassifer(ConversationID.class); + injectionSites.add(element); + factories.put(element, factory); + } else { + throw new InvalidAccessorException( + "Member must be a field or method: " + member.getName()); + } + + } + + if (!javaImpl.getCallbackMembers().isEmpty()) { + Map> callbackWires = new HashMap>(); + for (ComponentService service : component.getServices()) { + + RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference(); + if (callbackReference != null) { + List wires = callbackReference.getRuntimeWires(); + if (!wires.isEmpty()) { + callbackWires.put(wires.get(0).getSource().getInterfaceContract().getInterface().toString(), wires); + } + } + } + + for (Map.Entry entry : javaImpl.getCallbackMembers() + .entrySet()) { + List wires = callbackWires.get(entry.getKey()); + if (wires == null) { + // this can happen when there are no client wires to a + // component that has a callback + continue; + } + JavaElementImpl element = entry.getValue(); + ObjectFactory factory = new CallbackWireObjectFactory(element.getType(), proxyFactory, wires); + if (!(element.getAnchor() instanceof Constructor)) { + injectionSites.add(element); + } + factories.put(element, factory); + } + } + + for (JavaResourceImpl resource : javaImpl.getResources().values()) { + + ObjectFactory objectFactory; + Class type = resource.getElement().getType(); + if (ComponentContext.class.equals(type)) { + objectFactory = new ComponentContextFactory(component); + + } else if (RequestContext.class.equals(type)) { + objectFactory = new RequestContextObjectFactory(requestContextFactory, proxyFactory); + + } else { + boolean optional = resource.isOptional(); + String mappedName = resource.getMappedName(); + objectFactory = new ResourceObjectFactory(type, mappedName, optional, null); + } + factories.put(resource.getElement(), objectFactory); + if (!(resource.getElement().getAnchor() instanceof Constructor)) { + injectionSites.add(resource.getElement()); + } + } + + + } + + + @SuppressWarnings("unchecked") + private Injector[] createInjectors() { + + Injector[] injectors = (Injector[])new Injector[injectionSites.size()]; + + int i = 0; + for (JavaElementImpl element : injectionSites) { + Object obj = factories.get(element); + if (obj != null) { + if (obj instanceof ObjectFactory) { + ObjectFactory factory = (ObjectFactory)obj; + Member member = (Member)element.getAnchor(); + if (element.getElementType() == ElementType.FIELD) { + injectors[i++] = new FieldInjector((Field)member, factory); + } else if (element.getElementType() == ElementType.PARAMETER && member instanceof Method) { + injectors[i++] = new MethodInjector((Method)member, factory); + } else if (member instanceof Constructor) { + // Ignore + } else { + throw new AssertionError(String.valueOf(element)); + } + } else { + injectors[i++] = createMultiplicityInjector(element, (List>)obj); + } + } + } + return injectors; + } + + @SuppressWarnings("unchecked") + protected Injector createMultiplicityInjector(JavaElementImpl element, List> factories) { + Class interfaceType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + + if (element.getAnchor() instanceof Field) { + Field field = (Field)element.getAnchor(); + if (field.getType().isArray()) { + return new FieldInjector(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector(field, new ListMultiplicityObjectFactory(factories)); + } + } else if (element.getAnchor() instanceof Method) { + Method method = (Method)element.getAnchor(); + if (method.getParameterTypes()[0].isArray()) { + return new MethodInjector(method, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new MethodInjector(method, new ListMultiplicityObjectFactory(factories)); + } + } else { + throw new InvalidAccessorException("Member must be a field or method: " + element.getName()); + } + } + + private static class ComponentContextFactory implements ObjectFactory { + + RuntimeComponent component; + + private ComponentContextFactory(RuntimeComponent component) { + this.component = component; + } + + public Object getInstance() throws ObjectCreationException { + return component.getComponentContext(); + } + + } + + + private static class RequestContextObjectFactory implements ObjectFactory { + + private RequestContextFactory factory; + private ProxyFactory proxyFactory; + + public RequestContextObjectFactory(RequestContextFactory factory) { + this(factory, null); + } + + public RequestContextObjectFactory(RequestContextFactory factory, ProxyFactory proxyFactory) { + this.factory = factory; + this.proxyFactory = proxyFactory; + } + + public RequestContext getInstance() throws ObjectCreationException { + if (factory != null) { + return factory.createRequestContext(); + } else { + return new RequestContextImpl(proxyFactory); + } + } + + } + +} diff --git a/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java b/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java new file mode 100644 index 0000000000..af09013b6e --- /dev/null +++ b/branches/sca-java-1.1/modules/implementation-osgi/src/main/java/org/apache/tuscany/sca/implementation/osgi/context/OSGiPropertyValueObjectFactory.java @@ -0,0 +1,225 @@ +/* + * 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.osgi.context; + + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.xml.DOMDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * + * Process properties and create property values. + * + * This code has been copied from the Java implementation to avoid dependencies on the Java implementation. + * + */ +public class OSGiPropertyValueObjectFactory { + protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl(); + boolean isSimpleType; + + + public OSGiPropertyValueObjectFactory() { + } + + public OSGiPropertyValueObjectFactory(Mediator mediator) { + } + + public ObjectFactory createValueFactory(Property property, Object propertyValue) { + + Class javaType = SimpleTypeMapperImpl.getJavaType(property.getXSDType()); + isSimpleType = isSimpleType(property); + Document doc = (Document)propertyValue; + Element rootElement = doc.getDocumentElement(); + if (property.isMany()) { + if (isSimpleType) { + String value = ""; + if (rootElement.getChildNodes().getLength() > 0) { + value = rootElement.getChildNodes().item(0).getTextContent(); + } + List values = + getSimplePropertyValues(value, javaType); + return new ListObjectFactoryImpl(property, + values, + isSimpleType, + javaType); + } else { + return new ListObjectFactoryImpl(property, + getComplexPropertyValues(doc), + isSimpleType, + javaType); + } + } else { + if (isSimpleType) { + String value = ""; + if (rootElement.getChildNodes().getLength() > 0) { + value = rootElement.getChildNodes().item(0).getTextContent(); + } + return new ObjectFactoryImpl(property, + value, + isSimpleType, + javaType); + } else { + Object value = getComplexPropertyValues(doc).get(0); + return new ObjectFactoryImpl(property, + value, + isSimpleType, + javaType); + } + + } + } + + private boolean isSimpleType(Property property) { + if (property.getXSDType() != null) { + return SimpleTypeMapperImpl.isSimpleXSDType(property.getXSDType()); + } else { + if (property instanceof Document) { + Document doc = (Document)property; + Element element = doc.getDocumentElement(); + if (element.getChildNodes().getLength() == 1 && + element.getChildNodes().item(0).getNodeType() == Node.TEXT_NODE) { + return true; + } + } + } + return false; + } + + private List getSimplePropertyValues(String concatenatedValue, Class javaType) { + List propValues = new ArrayList(); + StringTokenizer st = null; + if ( javaType.getName().equals("java.lang.String")) { + st = new StringTokenizer(concatenatedValue, "\""); + } else { + st = new StringTokenizer(concatenatedValue); + } + String aToken = null; + while (st.hasMoreTokens()) { + aToken = st.nextToken(); + if (aToken.trim().length() > 0) { + propValues.add(aToken); + } + } + return propValues; + } + + private List getComplexPropertyValues(Document document) { + Element rootElement = document.getDocumentElement(); + List propValues = new ArrayList(); + for (int count = 0 ; count < rootElement.getChildNodes().getLength() ; ++count) { + if (rootElement.getChildNodes().item(count).getNodeType() == Node.ELEMENT_NODE) { + propValues.add(rootElement.getChildNodes().item(count)); + } + } + return propValues; + } + + public abstract class ObjectFactoryImplBase implements ObjectFactory { + protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl(); + protected Property property; + protected Object propertyValue; + protected Class javaType; + protected DataType sourceDataType; + protected DataType targetDataType; + boolean isSimpleType; + + public ObjectFactoryImplBase(Property property, Object propertyValue, boolean isSimpleType, Class javaType) { + this.isSimpleType = isSimpleType; + this.property = property; + this.propertyValue = propertyValue; + this.javaType = javaType; + sourceDataType = + new DataTypeImpl(DOMDataBinding.NAME, Node.class, + new XMLType(null, this.property.getXSDType())); + TypeInfo typeInfo = null; + if (this.property.getXSDType() != null) { + if (SimpleTypeMapperImpl.isSimpleXSDType(this.property.getXSDType())) { + typeInfo = new TypeInfo(property.getXSDType(), true, null); + } else { + typeInfo = new TypeInfo(property.getXSDType(), false, null); + } + } else { + typeInfo = new TypeInfo(property.getXSDType(), false, null); + } + + XMLType xmlType = new XMLType(typeInfo); + String dataBinding = null; //(String)property.getExtensions().get(DataBinding.class.getName()); + if (dataBinding != null) { + targetDataType = new DataTypeImpl(dataBinding, javaType, xmlType); + } else { + targetDataType = new DataTypeImpl(dataBinding, javaType, xmlType); + } + } + } + + public class ObjectFactoryImpl extends ObjectFactoryImplBase { + public ObjectFactoryImpl(Property property, Object propertyValue, boolean isSimpleType, Class javaType) { + super(property, propertyValue, isSimpleType, javaType); + } + + @SuppressWarnings("unchecked") + public Object getInstance() throws ObjectCreationException { + if (isSimpleType) { + return simpleTypeMapper.toJavaObject(property.getXSDType(), (String)propertyValue, null); + } else { + return null; + } + } + } + + public class ListObjectFactoryImpl extends ObjectFactoryImplBase { + public ListObjectFactoryImpl(Property property, ListpropertyValues, boolean isSimpleType, Class javaType) { + super(property, propertyValues, isSimpleType, javaType); + } + + @SuppressWarnings("unchecked") + public List getInstance() throws ObjectCreationException { + if (isSimpleType) { + List values = new ArrayList(); + for (String aValue : (List)propertyValue) { + values.add(simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null)); + } + return values; + } else { + List instances = new ArrayList(); + for (Node aValue : (List)propertyValue) { + instances.add(aValue); + } + return instances; + } + } + } +} + -- cgit v1.2.3