summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org')
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java77
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java52
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java70
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java69
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java55
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java54
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java79
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java87
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java253
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java185
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ComponentNotFoundException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java346
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java40
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidSourceTypeException.java35
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java35
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoBindingException.java35
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/SourceServiceNotFoundException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WireCreationException.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java67
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/physical/DefaultPhysicalComponentBuilderRegistry.java70
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallableReferenceImpl.java60
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallbackReferenceImpl.java33
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java92
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextProvider.java44
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManager.java86
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManagerImpl.java107
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/InstanceFactory.java43
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java35
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ServiceReferenceImpl.java52
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/SystemSingletonAtomicComponent.java134
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java212
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentEvent.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStart.java47
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStop.java46
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java31
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java31
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java45
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java28
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java158
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java184
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java217
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java58
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java135
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java54
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java41
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperBase.java52
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java48
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java126
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java48
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java63
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java75
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java54
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java125
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java121
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java90
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java121
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java66
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java357
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java215
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java168
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java200
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java244
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java182
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java66
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java61
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java83
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java73
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java68
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java69
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java70
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java221
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java299
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java70
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java56
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java80
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java1415
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java65
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java63
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java67
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java62
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java66
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java59
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java65
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java60
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java65
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java58
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java244
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java67
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java60
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java256
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java806
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java57
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java60
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java59
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java55
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java56
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java62
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java73
-rwxr-xr-xsca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java55
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java33
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java80
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java68
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java179
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java70
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java145
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java114
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java156
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java133
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PhysicalComponent.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java399
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoComponentContextFactory.java41
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java203
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java69
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java33
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java51
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java121
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java65
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java251
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java125
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java58
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java71
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java81
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java61
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java66
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponent.java163
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java195
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java86
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java62
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java64
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaPhysicalComponentBuilder.java108
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java133
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/TargetMethodNotFoundException.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java41
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java112
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java103
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java141
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java61
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java38
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java58
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java548
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java37
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java384
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java61
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java45
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java41
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java33
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java56
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java69
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java164
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java122
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java63
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java155
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java32
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java160
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java99
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java73
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java75
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java57
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java51
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java54
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java48
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java32
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java57
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java55
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/Injector.java35
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java33
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java55
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java55
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java29
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java48
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java120
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java46
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java34
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java89
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java39
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java348
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java86
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java88
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java105
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java52
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java67
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java179
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java195
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java98
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java119
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java107
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java99
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java191
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java122
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/AbstractMarshallerExtension.java72
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/DefaultModelMarshallerRegistry.java97
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalChangeSetMarshaller.java97
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalOperationDefinitionMarshaller.java72
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalWireDefinitionMarshaller.java99
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractExtensibleMarshallerExtension.java61
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalComponentDefinitionMarshaller.java110
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalReferenceDefinitionMarshaller.java84
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalServiceDefinitionMarshaller.java84
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalComponentDefinitionMarshaller.java157
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalReferenceDefinitionMarshaller.java93
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalServiceDefinitionMarshaller.java93
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalComponentDefinition.java93
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalReferenceDefinition.java31
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalServiceDefinition.java31
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java54
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java64
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java120
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java78
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java68
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/ProxyMonitorFactory.java234
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java167
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java59
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java297
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java65
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java194
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java109
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java65
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireResolver.java54
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireTargetNotFoundException.java30
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/DefaultAutowireResolver.java160
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java301
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java100
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/ClassLoaderRegistryImpl.java50
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/MultiParentClassLoader.java402
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java83
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java100
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java70
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java95
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java144
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java137
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java32
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java116
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java125
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java36
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java41
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java144
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java101
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/ScdlContributionProcessor.java105
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java115
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java142
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java198
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java206
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java217
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java73
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java166
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java220
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java285
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java94
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java439
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java60
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java94
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java95
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java59
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java42
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingInterceptor.java172
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java48
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/ProxyServiceExtension.java115
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireImpl.java137
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java84
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java115
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java155
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInvocationHandler.java263
-rw-r--r--sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKProxyService.java92
306 files changed, 31012 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java
new file mode 100644
index 0000000000..34c8eced5a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java
@@ -0,0 +1,77 @@
+/*
+ * 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.core.binding.local;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * Base class for dispatching to a composite reference using the local binding
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractLocalTargetInvoker implements TargetInvoker {
+ protected boolean cacheable;
+
+ public boolean isCacheable() {
+ return cacheable;
+ }
+
+ public void setCacheable(boolean cacheable) {
+ this.cacheable = cacheable;
+ }
+
+ public boolean isOptimizable() {
+ return isCacheable(); // we only need to check if the scopes are correct
+ }
+
+ public Object invokeTarget(final Object payload, short sequence) throws InvocationTargetException {
+ throw new InvocationTargetException(new UnsupportedOperationException());
+ }
+
+ protected Message invoke(InvocationChain chain, TargetInvoker invoker, Message msg) throws Throwable {
+ Interceptor headInterceptor = chain.getHeadInterceptor();
+ if (headInterceptor == null) {
+ try {
+ // short-circuit the dispatch and invoke the target directly
+ if (invoker == null) {
+ String name = chain.getOperation().getName();
+ throw new AssertionError("No target invoker [" + name + "]");
+ }
+ return invoker.invoke(msg);
+ } catch (InvocationRuntimeException e) {
+ // the cause was thrown by the target so throw it
+ throw e.getCause();
+ }
+ } else {
+ msg.setTargetInvoker(invoker);
+ return headInterceptor.invoke(msg);
+ }
+ }
+
+ @Override
+ public AbstractLocalTargetInvoker clone() throws CloneNotSupportedException {
+ return (AbstractLocalTargetInvoker) super.clone();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java
new file mode 100644
index 0000000000..63a9147b29
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.binding.local;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.ServiceBinding;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.BindingBuilderExtension;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * Creates runtime artifacts for the local binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalBindingBuilder extends BindingBuilderExtension<LocalBindingDefinition> {
+
+ protected Class<LocalBindingDefinition> getBindingType() {
+ return LocalBindingDefinition.class;
+ }
+
+ public ServiceBinding build(ServiceDefinition serviceDefinition,
+ LocalBindingDefinition bindingDefinition,
+ DeploymentContext context) throws BuilderException {
+ return new LocalServiceBinding(serviceDefinition.getUri());
+ }
+
+
+ public ReferenceBinding build(ReferenceDefinition referenceDefinition,
+ LocalBindingDefinition bindingDefinition,
+ DeploymentContext context) throws BuilderException {
+ return new LocalReferenceBinding(referenceDefinition.getUri(), bindingDefinition.getTargetUri());
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java
new file mode 100644
index 0000000000..9317a47457
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.binding.local;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.model.BindingDefinition;
+
+
+/**
+ * Represents the local by-reference binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalBindingDefinition extends BindingDefinition {
+
+ public LocalBindingDefinition() {
+ }
+
+ public LocalBindingDefinition(URI targetUri) {
+ super(targetUri);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java
new file mode 100644
index 0000000000..3442f1ca4c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.binding.local;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * Loader responsible for handling the local binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalBindingLoader extends LoaderExtension<LocalBindingDefinition> {
+
+ /**
+ * Constructor specifies the registry to register with.
+ *
+ * @param registry the LoaderRegistry this loader should register with
+ */
+ public LocalBindingLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return Wire.LOCAL_BINDING;
+ }
+
+ public LocalBindingDefinition load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ String uri = reader.getAttributeValue(null, "uri");
+ if (uri != null) {
+ try {
+ return new LocalBindingDefinition(new URI(uri));
+ } catch (URISyntaxException e) {
+ throw new LoaderException(e);
+ }
+ }
+ return new LocalBindingDefinition();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java
new file mode 100644
index 0000000000..c505ee99ab
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core.binding.local;
+
+import java.util.Map;
+
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.MessageImpl;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * Dispatches a callback invocation to the callback instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalCallbackTargetInvoker extends AbstractLocalTargetInvoker {
+ private Operation operation;
+ private Wire wire;
+
+ public LocalCallbackTargetInvoker(Operation operation, Wire wire) {
+ assert operation != null : "Operation method cannot be null";
+ this.operation = operation;
+ this.wire = wire;
+ }
+
+ public Message invoke(Message msg) throws InvocationRuntimeException {
+ try {
+ return invoke(operation, msg);
+ } catch (Throwable e) {
+ Message faultMsg = new MessageImpl();
+ faultMsg.setBodyWithFault(e);
+ return faultMsg;
+ }
+ }
+
+ private Message invoke(Operation operation, Message msg) throws Throwable {
+ //TODO optimize as this is slow in local invocations
+ Map<Operation<?>, InvocationChain> chains = wire.getCallbackInvocationChains();
+ InvocationChain chain = chains.get(operation);
+ TargetInvoker invoker = chain.getTargetInvoker();
+ return invoke(chain, invoker, msg);
+ }
+
+ @Override
+ public LocalCallbackTargetInvoker clone() throws CloneNotSupportedException {
+ return (LocalCallbackTargetInvoker) super.clone();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java
new file mode 100644
index 0000000000..69c5bcd35d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.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.core.binding.local;
+
+import java.net.URI;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.CoreRuntimeException;
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import org.apache.tuscany.spi.extension.ReferenceBindingExtension;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * The runtime representaion of the local reference binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalReferenceBinding extends ReferenceBindingExtension {
+
+ public LocalReferenceBinding(URI name, URI targetUri) throws CoreRuntimeException {
+ super(name, targetUri);
+ }
+
+ public QName getBindingType() {
+ return Wire.LOCAL_BINDING;
+ }
+
+ public TargetInvoker createTargetInvoker(String name, Operation operation)
+ throws TargetInvokerCreationException {
+ if (operation.isCallback()) {
+ return new LocalCallbackTargetInvoker(operation, wire);
+ } else {
+ return new LocalTargetInvoker(operation, wire);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java
new file mode 100644
index 0000000000..864dfea2f9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.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.core.binding.local;
+
+import java.net.URI;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.CoreRuntimeException;
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import org.apache.tuscany.spi.extension.ServiceBindingExtension;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * The runtime representaion of the local service binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalServiceBinding extends ServiceBindingExtension {
+
+ public LocalServiceBinding(URI name) throws CoreRuntimeException {
+ super(name);
+ }
+
+ public QName getBindingType() {
+ return Wire.LOCAL_BINDING;
+ }
+
+ public TargetInvoker createTargetInvoker(String name, Operation operation)
+ throws TargetInvokerCreationException {
+ if (operation.isCallback()) {
+ return new LocalCallbackTargetInvoker(operation, getWire());
+ } else {
+ return new LocalTargetInvoker(operation, getWire());
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java
new file mode 100644
index 0000000000..b89a70a9e0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.binding.local;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.util.UriHelper;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.MessageImpl;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * Dispatches an invocation through a composite service or reference using the local binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalTargetInvoker extends AbstractLocalTargetInvoker {
+ private InvocationChain chain;
+ private URI fromAddress;
+ private boolean contractHasCallback;
+
+ public LocalTargetInvoker(Operation operation, Wire wire) {
+ assert operation != null;
+ chain = wire.getInvocationChains().get(operation);
+ assert chain != null;
+ if (wire.getSourceUri() != null) {
+ fromAddress = URI.create(UriHelper.getBaseName(wire.getSourceUri()));
+ }
+ contractHasCallback = !wire.getCallbackInvocationChains().isEmpty();
+ }
+
+ @Override
+ public LocalTargetInvoker clone() throws CloneNotSupportedException {
+ return (LocalTargetInvoker) super.clone();
+ }
+
+ public Message invoke(Message msg) throws InvocationRuntimeException {
+ try {
+ TargetInvoker invoker = chain.getTargetInvoker();
+ assert invoker != null;
+ // Pushing the from address only needs to happen in the outbound (forward) direction for callbacks
+ if (contractHasCallback) {
+ //JFM do we need this?
+ msg.pushCallbackUri(fromAddress);
+ }
+
+ return invoke(chain, invoker, msg);
+ } catch (Throwable e) {
+ Message faultMsg = new MessageImpl();
+ faultMsg.setBodyWithFault(e);
+ return faultMsg;
+ }
+ }
+
+
+ public boolean isOptimizable() {
+ return true;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java
new file mode 100644
index 0000000000..a5083f77a9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java
@@ -0,0 +1,87 @@
+/*
+ * 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.core.bootstrap;
+
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.implementation.java.Introspector;
+import org.apache.tuscany.spi.loader.Loader;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+
+import org.apache.tuscany.core.resolver.AutowireResolver;
+import org.apache.tuscany.host.MonitorFactory;
+
+/**
+ * Interface that abstracts the process used to create a running Tuscany system. Implementation of this may provide
+ * different mechanisms for creating the primoridal system components used to boot the core to the level where it can
+ * support end-user applications.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Bootstrapper {
+ /**
+ * Return the MonitorFactory being used by the implementation to provide monitor interfaces for the primordial
+ * components.
+ *
+ * @return the MonitorFactory being used by the bootstrapper
+ */
+ MonitorFactory getMonitorFactory();
+
+ /**
+ * Create a Deployer that can be used to deploy the system definition. This will most likely only support a small
+ * subset of the available programming model.
+ *
+ * @return a new primordial Deployer
+ */
+ Deployer createDeployer();
+
+ /**
+ * Create a Loader for parsing a system definition represented as a XML SCDL file.
+ *
+ * @param propertyFactory the StAXPropertyFactory to be used to parse property values
+ * @param introspector the introspector to be used to extract component type information from a Java class
+ * @return a new prmordial Loader
+ */
+ Loader createLoader(PropertyObjectFactory propertyFactory, Introspector introspector);
+
+ /**
+ * Create a ScopeRegistry that supports the Scopes supported for primordial components
+ *
+ * @param workContext the WorkContext the Scopes should use
+ * @return a new primordial ScopeRegistry
+ */
+ ScopeRegistry createScopeRegistry(WorkContext workContext);
+
+ /**
+ * Create a Connector that can wire together primordial components.
+ *
+ * @return a new primordial Connector
+ */
+ Connector getConnector();
+
+ /**
+ * Returns the AutowireResolver that resolves autowire targets
+ *
+ * @return the AutowireResolver that resolves autowire targets
+ */
+ AutowireResolver getAutowireResolver();
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java
new file mode 100644
index 0000000000..073b9770f8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java
@@ -0,0 +1,253 @@
+/*
+ * 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.core.bootstrap;
+
+import javax.xml.stream.XMLInputFactory;
+
+import org.apache.tuscany.spi.builder.Builder;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.Introspector;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+
+import org.apache.tuscany.core.binding.local.LocalBindingBuilder;
+import org.apache.tuscany.core.binding.local.LocalBindingDefinition;
+import org.apache.tuscany.core.binding.local.LocalBindingLoader;
+import org.apache.tuscany.core.builder.BuilderRegistryImpl;
+import org.apache.tuscany.core.component.ComponentManager;
+import org.apache.tuscany.core.component.WorkContextImpl;
+import org.apache.tuscany.core.component.scope.CompositeScopeObjectFactory;
+import org.apache.tuscany.core.component.scope.ScopeRegistryImpl;
+import org.apache.tuscany.core.deployer.DeployerImpl;
+import org.apache.tuscany.core.idl.java.InterfaceJavaLoader;
+import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl;
+import org.apache.tuscany.core.implementation.IntrospectionRegistryImpl;
+import org.apache.tuscany.core.implementation.composite.CompositeLoader;
+import org.apache.tuscany.core.implementation.composite.SystemCompositeBuilder;
+import org.apache.tuscany.core.implementation.processor.ConstructorProcessor;
+import org.apache.tuscany.core.implementation.processor.DestroyProcessor;
+import org.apache.tuscany.core.implementation.processor.EagerInitProcessor;
+import org.apache.tuscany.core.implementation.processor.HeuristicPojoProcessor;
+import org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl;
+import org.apache.tuscany.core.implementation.processor.InitProcessor;
+import org.apache.tuscany.core.implementation.processor.MonitorProcessor;
+import org.apache.tuscany.core.implementation.processor.PropertyProcessor;
+import org.apache.tuscany.core.implementation.processor.ReferenceProcessor;
+import org.apache.tuscany.core.implementation.processor.ResourceProcessor;
+import org.apache.tuscany.core.implementation.processor.ScopeProcessor;
+import org.apache.tuscany.core.implementation.processor.ServiceProcessor;
+import org.apache.tuscany.core.implementation.system.builder.SystemComponentBuilder;
+import org.apache.tuscany.core.implementation.system.loader.SystemComponentTypeLoader;
+import org.apache.tuscany.core.implementation.system.loader.SystemCompositeComponentTypeLoader;
+import org.apache.tuscany.core.implementation.system.loader.SystemImplementationLoader;
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+import org.apache.tuscany.core.implementation.system.model.SystemImplementation;
+import org.apache.tuscany.core.loader.ComponentLoader;
+import org.apache.tuscany.core.loader.ComponentTypeElementLoader;
+import org.apache.tuscany.core.loader.IncludeLoader;
+import org.apache.tuscany.core.loader.LoaderRegistryImpl;
+import org.apache.tuscany.core.loader.PropertyLoader;
+import org.apache.tuscany.core.loader.ReferenceLoader;
+import org.apache.tuscany.core.loader.ServiceLoader;
+import org.apache.tuscany.core.property.PropertyObjectFactoryImpl;
+import org.apache.tuscany.core.resolver.AutowireResolver;
+import org.apache.tuscany.host.MonitorFactory;
+
+/**
+ * A default implementation of a Bootstrapper. Please see the documentation on the individual methods for how the
+ * primordial components are created.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultBootstrapper implements Bootstrapper {
+ private final MonitorFactory monitorFactory;
+ private final XMLInputFactory xmlFactory;
+ private final ComponentManager componentManager;
+ private final AutowireResolver resolver;
+ private final Connector connector;
+
+ /**
+ * Create a default bootstrapper.
+ *
+ * @param monitorFactory the MonitorFactory to be used to create monitors for the primordial components
+ * @param xmlFactory the XMLInputFactory to be used by the components to load XML artifacts
+ * @param componentManager the component manager for the runtime instance
+ * @param resolver the autowire resolver for the runtime instance
+ * @param connector the connector for the runtime instance
+ */
+ public DefaultBootstrapper(MonitorFactory monitorFactory,
+ XMLInputFactory xmlFactory,
+ ComponentManager componentManager,
+ AutowireResolver resolver,
+ Connector connector
+ ) {
+ this.monitorFactory = monitorFactory;
+ this.xmlFactory = xmlFactory;
+ this.componentManager = componentManager;
+ this.resolver = resolver;
+ this.connector = connector;
+ }
+
+ /**
+ * Returns the MonitorFactory being used by this bootstrapper.
+ *
+ * @return the MonitorFactory being used by this bootstrapper
+ */
+ public MonitorFactory getMonitorFactory() {
+ return monitorFactory;
+ }
+
+ /**
+ * Create primordial deployer that can be used to load the system definition.
+ *
+ * @return the primordial deployer
+ */
+ public Deployer createDeployer() {
+ ScopeRegistry scopeRegistry = createScopeRegistry(new WorkContextImpl());
+ Builder builder = createBuilder(scopeRegistry);
+ JavaInterfaceProcessorRegistry interfaceIntrospector = new JavaInterfaceProcessorRegistryImpl();
+ Introspector introspector = createIntrospector(interfaceIntrospector);
+ LoaderRegistry loader = createLoader(new PropertyObjectFactoryImpl(), introspector);
+ DeployerImpl deployer = new DeployerImpl(xmlFactory, loader, builder, componentManager, resolver, connector);
+ deployer.setMonitor(getMonitorFactory().getMonitor(ScopeContainerMonitor.class));
+ return deployer;
+ }
+
+ /**
+ * Create a basic ScopeRegistry containing the ScopeContainers that are available to components in the system
+ * definition. The implementation returned only support COMPOSITE scope.
+ *
+ * @param workContext the WorkContext the scopes should use
+ * @return a new ScopeRegistry
+ */
+ public ScopeRegistry createScopeRegistry(WorkContext workContext) {
+ ScopeRegistry scopeRegistry = new ScopeRegistryImpl();
+ new CompositeScopeObjectFactory(scopeRegistry, monitorFactory.getMonitor(ScopeContainerMonitor.class));
+ return scopeRegistry;
+ }
+
+ /**
+ * Create a Loader that can be used to parse an XML file containing the SCDL for the system definition. The
+ * following Implementation types are supported: <ul> <li>SystemImplementation</li>
+ * <li>SystemCompositeImplementation</li> </ul> and the following SCDL elements are supported: <ul>
+ * <li>composite</li> <li>component</li> <li>componentType</li> <li>interface.java</li> <li>property</li>
+ * <li>reference</li> <li>service</li> <li>implementation.system</li> </ul> Note the Java component type and the
+ * WSDL interface type are not supported.
+ *
+ * @param propertyFactory the StAXPropertyFactory to be used for parsing Property values
+ * @param introspector the Introspector to be used to inspect component implementations
+ * @return a new StAX XML loader
+ */
+ public LoaderRegistry createLoader(PropertyObjectFactory propertyFactory, Introspector introspector) {
+ LoaderRegistryImpl loaderRegistry =
+ new LoaderRegistryImpl(monitorFactory.getMonitor(LoaderRegistryImpl.Monitor.class));
+
+ // register component type loaders
+ loaderRegistry.registerLoader(SystemImplementation.class, new SystemComponentTypeLoader(introspector));
+ loaderRegistry.registerLoader(SystemCompositeImplementation.class,
+ new SystemCompositeComponentTypeLoader(loaderRegistry));
+
+ // register element loaders
+ registerLoader(loaderRegistry, new ComponentLoader(loaderRegistry, propertyFactory));
+ registerLoader(loaderRegistry, new ComponentTypeElementLoader(loaderRegistry));
+ registerLoader(loaderRegistry, new CompositeLoader(loaderRegistry, null));
+ registerLoader(loaderRegistry, new IncludeLoader(loaderRegistry));
+ JavaInterfaceProcessorRegistryImpl processorRegistry = new JavaInterfaceProcessorRegistryImpl();
+ registerLoader(loaderRegistry, new InterfaceJavaLoader(loaderRegistry, processorRegistry));
+ registerLoader(loaderRegistry, new PropertyLoader(loaderRegistry));
+ registerLoader(loaderRegistry, new ReferenceLoader(loaderRegistry));
+ registerLoader(loaderRegistry, new ServiceLoader(loaderRegistry));
+ registerLoader(loaderRegistry, new SystemImplementationLoader(loaderRegistry));
+ registerLoader(loaderRegistry, new LocalBindingLoader(loaderRegistry));
+ return loaderRegistry;
+ }
+
+ /**
+ * Create new Introspector for extracting a ComponentType definition from a Java class.
+ *
+ * @return a new Introspector
+ */
+ public Introspector createIntrospector(JavaInterfaceProcessorRegistry registry) {
+ ImplementationProcessorService service = new ImplementationProcessorServiceImpl(registry);
+ IntrospectionRegistryImpl.Monitor monitor = monitorFactory.getMonitor(IntrospectionRegistryImpl.Monitor.class);
+ IntrospectionRegistryImpl introspectionRegistry = new IntrospectionRegistryImpl(monitor);
+ introspectionRegistry.registerProcessor(new ConstructorProcessor(service));
+ introspectionRegistry.registerProcessor(new DestroyProcessor());
+ introspectionRegistry.registerProcessor(new InitProcessor());
+ introspectionRegistry.registerProcessor(new EagerInitProcessor());
+ introspectionRegistry.registerProcessor(new ScopeProcessor());
+ introspectionRegistry.registerProcessor(new PropertyProcessor(service));
+ introspectionRegistry.registerProcessor(new ReferenceProcessor(registry));
+ introspectionRegistry.registerProcessor(new ResourceProcessor());
+ introspectionRegistry.registerProcessor(new ServiceProcessor(service));
+ introspectionRegistry.registerProcessor(new HeuristicPojoProcessor(service));
+ introspectionRegistry.registerProcessor(new MonitorProcessor(monitorFactory, service));
+ return introspectionRegistry;
+ }
+
+ /**
+ * Create a new Connector that can be used to wire primordial components together.
+ *
+ * @return a new Connector
+ */
+ public Connector getConnector() {
+ return connector;
+ }
+
+
+ public AutowireResolver getAutowireResolver() {
+ return resolver;
+ }
+
+ /**
+ * Helper method for registering a loader with the registry. The Loader is registered once for the QName returned by
+ * its {@link LoaderExtension#getXMLType()} method.
+ *
+ * @param registry the LoaderRegistry to register with
+ * @param loader the Loader to register
+ */
+ protected void registerLoader(LoaderRegistry registry, LoaderExtension<?> loader) {
+ registry.registerLoader(loader.getXMLType(), loader);
+ }
+
+ /**
+ * Create a Builder that can be used to build the components in the system definition. The default implementation
+ * only supports implementations from the system programming model.
+ *
+ * @param scopeRegistry the ScopeRegistry defining the component scopes that will be supported
+ * @return a new Builder
+ */
+ private Builder createBuilder(ScopeRegistry scopeRegistry) {
+ BuilderRegistryImpl builderRegistry =
+ new BuilderRegistryImpl(scopeRegistry);
+ SystemCompositeBuilder builder = new SystemCompositeBuilder(builderRegistry);
+ builderRegistry.register(SystemCompositeImplementation.class, builder);
+ builderRegistry.register(SystemImplementation.class, new SystemComponentBuilder());
+ builderRegistry.register(LocalBindingDefinition.class, new LocalBindingBuilder());
+ return builderRegistry;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java
new file mode 100644
index 0000000000..33dd2175f9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java
@@ -0,0 +1,185 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.builder.BindingBuilder;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.BuilderRegistry;
+import org.apache.tuscany.spi.builder.ComponentBuilder;
+import org.apache.tuscany.spi.builder.ScopeNotFoundException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.component.ServiceBinding;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+import org.apache.tuscany.core.binding.local.LocalBindingDefinition;
+import org.apache.tuscany.core.implementation.composite.ReferenceImpl;
+import org.apache.tuscany.core.implementation.composite.ServiceImpl;
+
+/**
+ * The default builder registry in the runtime
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class BuilderRegistryImpl implements BuilderRegistry {
+ private ScopeRegistry scopeRegistry;
+
+ private final Map<Class<? extends Implementation<?>>, ComponentBuilder<? extends Implementation<?>>> componentBuilders =
+ new HashMap<Class<? extends Implementation<?>>, ComponentBuilder<? extends Implementation<?>>>();
+ private final Map<Class<? extends BindingDefinition>, BindingBuilder<? extends BindingDefinition>> bindingBuilders =
+ new HashMap<Class<? extends BindingDefinition>, BindingBuilder<? extends BindingDefinition>>();
+
+ public BuilderRegistryImpl(@org.osoa.sca.annotations.Reference ScopeRegistry scopeRegistry) {
+ this.scopeRegistry = scopeRegistry;
+ }
+
+ public <I extends Implementation<?>> void register(Class<I> implClass, ComponentBuilder<I> builder) {
+ componentBuilders.put(implClass, builder);
+ }
+
+ public <I extends Implementation<?>> void unregister(Class<I> implClass) {
+ componentBuilders.remove(implClass);
+ }
+
+ public <B extends BindingDefinition> void register(Class<B> implClass, BindingBuilder<B> builder) {
+ bindingBuilders.put(implClass, builder);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <I extends Implementation<?>> Component build(
+ ComponentDefinition<I> componentDefinition,
+ DeploymentContext context) throws BuilderException {
+ Class<?> implClass = componentDefinition.getImplementation().getClass();
+ // noinspection SuspiciousMethodCalls
+ ComponentBuilder<I> componentBuilder = (ComponentBuilder<I>) componentBuilders.get(implClass);
+ if (componentBuilder == null) {
+ String name = implClass.getName();
+ throw new NoRegisteredBuilderException("No builder registered for implementation", name);
+ }
+ Component component = componentBuilder.build(componentDefinition, context);
+ assert component != null;
+ component.setDefaultPropertyValues(componentDefinition.getPropertyValues());
+ Scope scope = componentDefinition.getImplementation().getComponentType().getImplementationScope();
+ if (scope == Scope.SYSTEM || scope == Scope.COMPOSITE) {
+ component.setScopeContainer(context.getCompositeScope());
+ } else {
+ // Check for conversational contract if conversational scope
+ if (scope == Scope.CONVERSATION) {
+ boolean hasConversationalContract = false;
+ ComponentType<ServiceDefinition, ReferenceDefinition, ?> componentType =
+ componentDefinition.getImplementation().getComponentType();
+ Map<String, ServiceDefinition> services = componentType.getServices();
+ for (ServiceDefinition serviceDef : services.values()) {
+ ServiceContract<?> contract = serviceDef.getServiceContract();
+ if (contract.isConversational()) {
+ hasConversationalContract = true;
+ break;
+ }
+ }
+ if (!hasConversationalContract) {
+ String name = implClass.getName();
+ throw new NoConversationalContractException(
+ "No conversational contract for conversational implementation", name);
+ }
+ }
+ // Now it's ok to set the scope container
+ ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(scope);
+ if (scopeContainer == null) {
+ throw new ScopeNotFoundException(scope.toString());
+ }
+ component.setScopeContainer(scopeContainer);
+ }
+ context.getComponents().put(component.getUri(), component);
+ ComponentType<?, ?, ?> componentType = componentDefinition.getImplementation().getComponentType();
+ assert componentType != null : "Component type must be set";
+ return component;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public Service build(ServiceDefinition serviceDefinition, DeploymentContext context) throws BuilderException {
+ URI uri = serviceDefinition.getUri();
+ ServiceContract<?> serviceContract = serviceDefinition.getServiceContract();
+ if (serviceDefinition.getBindings().isEmpty()) {
+ // if no bindings are configured, default to the local binding.
+ // this should be changed to allow runtime selection
+ if (serviceDefinition.getBindings().isEmpty()) {
+ // TODO JFM implement capability for the runtime to choose a binding
+ serviceDefinition.addBinding(new LocalBindingDefinition());
+ }
+ }
+ URI targetUri = serviceDefinition.getTarget();
+ Service service = new ServiceImpl(uri, serviceContract, targetUri);
+ for (BindingDefinition definition : serviceDefinition.getBindings()) {
+ Class<?> bindingClass = definition.getClass();
+ // noinspection SuspiciousMethodCalls
+ BindingBuilder bindingBuilder = bindingBuilders.get(bindingClass);
+ if (bindingBuilder == null) {
+ throw new NoRegisteredBuilderException("No builder registered for type", bindingClass.getName());
+ }
+ ServiceBinding binding = bindingBuilder.build(serviceDefinition, definition, context);
+ service.addServiceBinding(binding);
+ }
+ return service;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Reference build(ReferenceDefinition referenceDefinition, DeploymentContext context) throws BuilderException {
+ URI uri = referenceDefinition.getUri();
+ ServiceContract<?> contract = referenceDefinition.getServiceContract();
+ if (referenceDefinition.getBindings().isEmpty()) {
+ // if no bindings are configured, default to the local binding.
+ // this should be changed to allow runtime selection
+ if (referenceDefinition.getBindings().isEmpty()) {
+ // TODO JFM implement capability for the runtime to choose a binding
+ referenceDefinition.addBinding(new LocalBindingDefinition());
+ }
+ }
+
+ Reference reference = new ReferenceImpl(uri, contract);
+ for (BindingDefinition bindingDefinition : referenceDefinition.getBindings()) {
+ Class<?> bindingClass = bindingDefinition.getClass();
+ // noinspection SuspiciousMethodCalls
+ BindingBuilder bindingBuilder = bindingBuilders.get(bindingClass);
+ ReferenceBinding binding = bindingBuilder.build(referenceDefinition, bindingDefinition, context);
+ reference.addReferenceBinding(binding);
+
+ }
+ return reference;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ComponentNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ComponentNotFoundException.java
new file mode 100644
index 0000000000..a46e038cb9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ComponentNotFoundException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Indicates a component was not found during wiring
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentNotFoundException extends WiringException {
+
+ public ComponentNotFoundException(String message, URI name) {
+ super(message, name, name);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java
new file mode 100644
index 0000000000..2e1af8d8f5
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java
@@ -0,0 +1,346 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.builder.WiringException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.Invocable;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.component.ServiceBinding;
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ReferenceTarget;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.apache.tuscany.spi.model.physical.PhysicalWireDefinition;
+import org.apache.tuscany.spi.services.work.WorkScheduler;
+import org.apache.tuscany.spi.util.UriHelper;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WirePostProcessorRegistry;
+
+import org.apache.tuscany.core.component.ComponentManager;
+import org.apache.tuscany.core.wire.InvocationChainImpl;
+import org.apache.tuscany.core.wire.InvokerInterceptor;
+import org.apache.tuscany.core.wire.NonBlockingInterceptor;
+import org.apache.tuscany.core.wire.WireImpl;
+import org.apache.tuscany.core.wire.WireUtils;
+
+/**
+ * The default connector implmentation
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class ConnectorImpl implements Connector {
+ private WirePostProcessorRegistry postProcessorRegistry;
+ private ComponentManager componentManager;
+ private WorkContext workContext;
+ private WorkScheduler scheduler;
+
+ public ConnectorImpl(ComponentManager componentManager) {
+ this.componentManager = componentManager;
+ }
+
+ @Constructor
+ public ConnectorImpl(
+ @org.osoa.sca.annotations.Reference WirePostProcessorRegistry processorRegistry,
+ @org.osoa.sca.annotations.Reference ComponentManager componentManager,
+ @org.osoa.sca.annotations.Reference WorkScheduler scheduler,
+ @org.osoa.sca.annotations.Reference WorkContext workContext) {
+ this.postProcessorRegistry = processorRegistry;
+ this.componentManager = componentManager;
+ this.scheduler = scheduler;
+ this.workContext = workContext;
+ }
+
+ /**
+ * <strong>Note this method will not work yet</strong>
+ * <p/>
+ * Wires a source and target component based on a wire defintion
+ *
+ * @param definition the wire definition
+ * @throws WiringException
+ */
+ public void connect(PhysicalWireDefinition definition) throws WiringException {
+ URI sourceUri = definition.getSourceUri();
+ assert sourceUri != null;
+ URI targetUri = definition.getTargetUri();
+ assert targetUri != null;
+ URI baseSourceUri = UriHelper.getDefragmentedName(sourceUri);
+ URI baseTargetUri = UriHelper.getDefragmentedName(targetUri);
+ String targetFragment = targetUri.getFragment();
+ Component source = componentManager.getComponent(baseSourceUri);
+ if (source == null) {
+ throw new ComponentNotFoundException("Wire source component not found", baseSourceUri);
+ }
+ Component target = componentManager.getComponent(baseTargetUri);
+ if (target == null) {
+ throw new ComponentNotFoundException("Wire target component not found", baseTargetUri);
+ }
+ ServiceContract<?> contract = null;
+ Wire wire = createWire(sourceUri, targetUri, contract, definition.getBindingType());
+ try {
+ attachInvokers(targetFragment, wire, source, target);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireCreationException("Error creating invoker", sourceUri, targetUri, e);
+ }
+ source.attachWire(wire);
+ throw new UnsupportedOperationException();
+ }
+
+ public void connect(ComponentDefinition<? extends Implementation<?>> definition) throws WiringException {
+ URI sourceUri = definition.getUri();
+ Component source = componentManager.getComponent(sourceUri);
+ if (source == null) {
+ throw new ComponentNotFoundException("Source not found", sourceUri);
+ }
+ ComponentType<?, ?, ?> type = definition.getImplementation().getComponentType();
+ if (type instanceof CompositeComponentType) {
+ CompositeComponentType<?, ?, ?> compositeType = (CompositeComponentType<?, ?, ?>) type;
+ for (ComponentDefinition<? extends Implementation<?>> child : compositeType.getComponents().values()) {
+ connect(child);
+ }
+ for (ServiceDefinition child : compositeType.getServices().values()) {
+ connect(child);
+ }
+ for (ReferenceDefinition child : compositeType.getReferences().values()) {
+ connect(child);
+ }
+ }
+ Map<String, ReferenceTarget> targets = definition.getReferenceTargets();
+ for (ReferenceTarget referenceTarget : targets.values()) {
+ List<Wire> wires = new ArrayList<Wire>();
+ String refName = referenceTarget.getReferenceName().getFragment();
+ ReferenceDefinition refDefinition = type.getReferences().get(refName);
+ assert refDefinition != null;
+ List<URI> uris = referenceTarget.getTargets();
+ for (URI uri : uris) {
+ URI targetUri = UriHelper.getDefragmentedName(uri);
+ Component target = componentManager.getComponent(targetUri);
+ if (target == null && !refDefinition.isRequired()) {
+ // a non-required reference, just skip
+ continue;
+ }
+ if (target == null) {
+ throw new ComponentNotFoundException("Target not found", targetUri);
+ }
+ String fragment = uri.getFragment();
+ URI sourceURI = refDefinition.getUri();
+ Wire wire = createWire(sourceURI, uri, refDefinition.getServiceContract(), Wire.LOCAL_BINDING);
+ try {
+ attachInvokers(fragment, wire, source, target);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireCreationException("Error creating invoker", sourceUri, targetUri, e);
+ }
+ if (postProcessorRegistry != null) {
+ postProcessorRegistry.process(wire);
+ }
+ optimize(source, target, wire);
+ wires.add(wire);
+ if (!wire.getCallbackInvocationChains().isEmpty()) {
+ target.attachCallbackWire(wire);
+ }
+ }
+ if (wires.size() > 1) {
+ // attach as a multiplicity
+ source.attachWires(wires);
+ } else if (wires.size() == 1) {
+ // attach as a single wire
+ Wire wire = wires.get(0);
+ source.attachWire(wire);
+ }
+ }
+ }
+
+ /**
+ * @deprecated
+ */
+ protected void connect(ServiceDefinition definition) throws WiringException {
+ URI uri = definition.getUri();
+ URI sourceUri = UriHelper.getDefragmentedName(uri);
+ URI targetUri = definition.getTarget();
+ URI baseTargetUri = UriHelper.getDefragmentedName(targetUri);
+ Component source = componentManager.getComponent(sourceUri);
+ if (source == null) {
+ throw new ComponentNotFoundException("Source not found", sourceUri);
+ }
+ Service service = source.getService(uri.getFragment());
+ if (service == null) {
+ throw new SourceServiceNotFoundException("Service not found on composite", uri);
+ }
+ Component target = componentManager.getComponent(baseTargetUri);
+ if (target == null) {
+ throw new ComponentNotFoundException("Target not found", sourceUri);
+ }
+ ServiceContract<?> contract = definition.getServiceContract();
+ // TODO if no binding, do local
+ for (ServiceBinding binding : service.getServiceBindings()) {
+ Wire wire = createWire(uri, targetUri, contract, binding.getBindingType());
+ binding.setWire(wire);
+ if (postProcessorRegistry != null) {
+ postProcessorRegistry.process(wire);
+ }
+ try {
+ attachInvokers(definition.getTarget().getFragment(), wire, binding, target);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireCreationException("Error creating invoker", sourceUri, baseTargetUri, e);
+ }
+ }
+ }
+
+ /**
+ * @deprecated
+ */
+ protected void connect(ReferenceDefinition definition) throws WiringException {
+ URI uri = definition.getUri();
+ URI sourceUri = UriHelper.getDefragmentedName(uri);
+ Component source = componentManager.getComponent(sourceUri);
+ if (source == null) {
+ throw new ComponentNotFoundException("Source not found", sourceUri);
+ }
+ Reference reference = source.getReference(uri.getFragment());
+ if (reference == null) {
+ throw new SourceServiceNotFoundException("Reference not found on composite", uri);
+ }
+
+ for (ReferenceBinding binding : reference.getReferenceBindings()) {
+ // create wire
+ if (Wire.LOCAL_BINDING.equals(binding.getBindingType())) {
+ URI targetUri = binding.getTargetUri();
+ ServiceContract<?> contract = binding.getBindingServiceContract();
+ QName type = binding.getBindingType();
+ Wire wire = createWire(sourceUri, targetUri, contract, type);
+ binding.setWire(wire);
+ // wire local bindings to their targets
+ Component target = componentManager.getComponent(UriHelper.getDefragmentedName(targetUri));
+ if (target == null) {
+ throw new ComponentNotFoundException("Target not found", sourceUri);
+ }
+ try {
+ attachInvokers(targetUri.getFragment(), wire, binding, target);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireCreationException("Error creating invoker", sourceUri, targetUri, e);
+ }
+ } else {
+ Wire wire = createWire(sourceUri, null, binding.getBindingServiceContract(), binding.getBindingType());
+ if (postProcessorRegistry != null) {
+ postProcessorRegistry.process(wire);
+ }
+ binding.setWire(wire);
+ }
+ }
+ }
+
+ protected Wire createWire(URI sourceURI, URI targetUri, ServiceContract<?> contract, QName bindingType) {
+ Wire wire = new WireImpl(bindingType);
+ wire.setSourceContract(contract);
+ wire.setSourceUri(sourceURI);
+ wire.setTargetUri(targetUri);
+ for (Operation<?> operation : contract.getOperations().values()) {
+ InvocationChain chain = new InvocationChainImpl(operation);
+ if (operation.isNonBlocking()) {
+ chain.addInterceptor(new NonBlockingInterceptor(scheduler, workContext));
+ }
+ chain.addInterceptor(new InvokerInterceptor());
+ wire.addInvocationChain(operation, chain);
+
+ }
+ for (Operation<?> operation : contract.getCallbackOperations().values()) {
+ InvocationChain chain = new InvocationChainImpl(operation);
+ if (operation.isNonBlocking()) {
+ chain.addInterceptor(new NonBlockingInterceptor(scheduler, workContext));
+ }
+ chain.addInterceptor(new InvokerInterceptor());
+ wire.addCallbackInvocationChain(operation, chain);
+ }
+ return wire;
+ }
+
+ private void attachInvokers(String name, Wire wire, Invocable source, Invocable target)
+ throws TargetInvokerCreationException {
+ for (InvocationChain chain : wire.getInvocationChains().values()) {
+ //String name = target.getUri().getFragment();
+ chain.setTargetInvoker(target.createTargetInvoker(name, chain.getOperation()));
+ }
+ for (InvocationChain chain : wire.getCallbackInvocationChains().values()) {
+ chain.setTargetInvoker(source.createTargetInvoker(null, chain.getOperation()));
+ }
+ }
+
+ protected void optimize(Component source, Component target, Wire wire) {
+ boolean optimizableScopes = isOptimizable(source.getScope(), target.getScope());
+ if (optimizableScopes && target.isOptimizable() && WireUtils.isOptimizable(wire)) {
+ wire.setOptimizable(true);
+ wire.setTarget((AtomicComponent) target);
+ } else {
+ wire.setOptimizable(false);
+ }
+ }
+
+ protected boolean isOptimizable(Scope pReferrer, Scope pReferee) {
+ if (pReferrer == Scope.UNDEFINED
+ || pReferee == Scope.UNDEFINED
+ || pReferrer == Scope.CONVERSATION
+ || pReferee == Scope.CONVERSATION) {
+ return false;
+ }
+ if (pReferee == pReferrer) {
+ return true;
+ } else if (pReferrer == Scope.STATELESS) {
+ return true;
+ } else if (pReferee == Scope.STATELESS) {
+ return false;
+ } else if (pReferrer == Scope.REQUEST && pReferee == Scope.SESSION) {
+ return true;
+ } else if (pReferrer == Scope.REQUEST && pReferee == Scope.COMPOSITE) {
+ return true;
+ } else if (pReferrer == Scope.REQUEST && pReferee == Scope.SYSTEM) {
+ return true;
+ } else if (pReferrer == Scope.SESSION && pReferee == Scope.COMPOSITE) {
+ return true;
+ } else if (pReferrer == Scope.SESSION && pReferee == Scope.SYSTEM) {
+ return true;
+ } else //noinspection SimplifiableIfStatement
+ if (pReferrer == Scope.SYSTEM && pReferee == Scope.COMPOSITE) {
+ // case where a service context points to a composite scoped component
+ return true;
+ } else {
+ return pReferrer == Scope.COMPOSITE && pReferee == Scope.SYSTEM;
+ }
+ }
+} \ No newline at end of file
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java
new file mode 100644
index 0000000000..183ccea1b8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Denotes an illegal callback
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalCallbackException extends WiringException {
+
+ public IllegalCallbackException(String message, String identifier, URI sourceUri, URI targetUri) {
+ super(message, identifier, sourceUri, targetUri);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java
new file mode 100644
index 0000000000..1a9c74aa3b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Denotes an attempt to wire incompatible interfaces
+ *
+ * @version $Rev$ $Date$
+ */
+public class IncompatibleInterfacesException extends WiringException {
+
+ public IncompatibleInterfacesException(URI source, URI target) {
+ super("Incompatible source and target interfaces", source, target);
+ }
+
+ public IncompatibleInterfacesException(URI source, URI target, Throwable throwable) {
+ super("Incompatible source and target interfaces", source, target, throwable);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidSourceTypeException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidSourceTypeException.java
new file mode 100644
index 0000000000..d9df445530
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidSourceTypeException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Denotes an invalid source type for a wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidSourceTypeException extends WiringException {
+
+ public InvalidSourceTypeException(String message, URI sourceUri, URI targetUri) {
+ super(message, sourceUri, targetUri);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java
new file mode 100644
index 0000000000..e3c26c75d2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Denotes an invalid target service for a wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidTargetTypeException extends WiringException {
+
+ public InvalidTargetTypeException(String message, URI sourceUri, URI targetUri) {
+ super(message, sourceUri, targetUri);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoBindingException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoBindingException.java
new file mode 100644
index 0000000000..c351013297
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoBindingException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Denotes no binding was specified for a wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class NoBindingException extends WiringException {
+
+ public NoBindingException(String message, URI sourceUri, URI targetUri) {
+ super(message, sourceUri, targetUri);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java
new file mode 100644
index 0000000000..3c49767333
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class NoCompatibleBindingsException extends WiringException {
+
+ public NoCompatibleBindingsException(URI sourceName, URI targetName) {
+ super("No compatible bindings for source and target", sourceName, targetName);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java
new file mode 100644
index 0000000000..71eb9ebd26
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.builder;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+
+/**
+ * Raised when a component has conversational scope but no conversational contract
+ *
+ * @version $Rev: 487877 $ $Date: 2006-12-16 15:32:16 -0500 (Sat, 16 Dec 2006) $
+ */
+public class NoConversationalContractException extends BuilderException {
+
+ public NoConversationalContractException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ public NoConversationalContractException(String message) {
+ super(message);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java
new file mode 100644
index 0000000000..340a20f239
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.builder;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+
+/**
+ * Raised when a builder cannot be found for a SCDL entry type
+ *
+ * @version $Rev$ $Date$
+ */
+public class NoRegisteredBuilderException extends BuilderException {
+
+ public NoRegisteredBuilderException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ public NoRegisteredBuilderException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/SourceServiceNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/SourceServiceNotFoundException.java
new file mode 100644
index 0000000000..7d3d49b937
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/SourceServiceNotFoundException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Indicates the source service of a wire was not found
+ *
+ * @version $Rev$ $Date$
+ */
+public class SourceServiceNotFoundException extends WiringException {
+
+ public SourceServiceNotFoundException(String message, URI sourceName) {
+ super(message, sourceName, null);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java
new file mode 100644
index 0000000000..f22b421aa7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Indicates the target service of a reference was not found
+ *
+ * @version $Rev$ $Date$
+ */
+public class TargetServiceNotFoundException extends WiringException {
+
+ public TargetServiceNotFoundException(String message, URI sourceName, URI targetName) {
+ super(message, sourceName, targetName);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WireCreationException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WireCreationException.java
new file mode 100644
index 0000000000..117bb23180
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WireCreationException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.builder;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * Denotes an error creating a wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class WireCreationException extends WiringException {
+
+ public WireCreationException(String message, URI sourceUri, Throwable e) {
+ super(message, sourceUri, null, e);
+ }
+
+ public WireCreationException(String message, URI sourceUri, URI targetUri, Throwable e) {
+ super(message, sourceUri, targetUri, e);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java
new file mode 100644
index 0000000000..6f611956be
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WirePostProcessor;
+import org.apache.tuscany.spi.wire.WirePostProcessorRegistry;
+
+/**
+ * The default implementation of a <code>WirePostProcessor</code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class WirePostProcessorRegistryImpl implements WirePostProcessorRegistry {
+
+ private final List<WirePostProcessor> processors = new ArrayList<WirePostProcessor>();
+
+ public void process(Wire wire) {
+ for (WirePostProcessor processor : processors) {
+ processor.process(wire);
+ }
+ }
+
+ public void register(WirePostProcessor processor) {
+ processors.add(processor);
+ }
+
+ public void unregister(WirePostProcessor processor) {
+ processors.remove(processor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java
new file mode 100644
index 0000000000..661dc8bfea
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.core.builder;
+
+import java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.builder.WiringException;
+
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+
+/**
+ * Formats {@link WiringException}s
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class WiringExceptionFormatter implements ExceptionFormatter {
+ private FormatterRegistry factory;
+
+ public WiringExceptionFormatter(@Reference FormatterRegistry factory) {
+ this.factory = factory;
+ factory.register(this);
+ }
+
+ public boolean canFormat(Class<?> type) {
+ return WiringException.class.isAssignableFrom(type);
+ }
+
+ @Destroy
+ public void destroy() {
+ factory.unregister(this);
+ }
+
+ public PrintWriter write(PrintWriter writer, Throwable exception) {
+ assert exception instanceof WiringException;
+ WiringException e = (WiringException) exception;
+ e.appendBaseMessage(writer);
+ if (e.getSourceUri() != null) {
+ writer.write("\nSource : " + e.getSourceUri());
+ }
+ if (e.getTargetUri() != null) {
+ writer.write("\nTarget : " + e.getTargetUri());
+ }
+ return writer;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/physical/DefaultPhysicalComponentBuilderRegistry.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/physical/DefaultPhysicalComponentBuilderRegistry.java
new file mode 100644
index 0000000000..c1baa27ed2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/builder/physical/DefaultPhysicalComponentBuilderRegistry.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.builder.physical;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.physical.PhysicalComponentBuilder;
+import org.apache.tuscany.spi.builder.physical.PhysicalComponentBuilderRegistry;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.model.physical.PhysicalComponentDefinition;
+
+/**
+ * Default map-based implementation of the physical component builder registry.
+ * <p/>
+ * TODO may be we can factor out all the registries into a parameterized one.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultPhysicalComponentBuilderRegistry implements PhysicalComponentBuilderRegistry {
+
+ // Internal cache
+ private Map<Class<? extends PhysicalComponentDefinition>,
+ PhysicalComponentBuilder<? extends PhysicalComponentDefinition, ? extends Component>> registry =
+ new ConcurrentHashMap<Class<? extends PhysicalComponentDefinition>,
+ PhysicalComponentBuilder<? extends PhysicalComponentDefinition, ? extends Component>>();
+
+ /**
+ * Registers a physical component builder.
+ *
+ * @param <PCD> Type of the physical component definition.
+ * @param definitionClass Class of the physical component definition.
+ * @param builder Builder for the physical component definition.
+ */
+ public <PCD extends PhysicalComponentDefinition,
+ C extends Component> void register(Class<PCD> definitionClass, PhysicalComponentBuilder<PCD, C> builder) {
+ registry.put(definitionClass, builder);
+ }
+
+ /**
+ * Builds a physical component from component definition.
+ * @param componentDefinition Component definition.
+ * @return Component to be built.
+ */
+ @SuppressWarnings("unchecked")
+ public Component build(PhysicalComponentDefinition componentDefinition) throws BuilderException {
+
+ PhysicalComponentBuilder builder = registry.get(componentDefinition.getClass());
+ return builder.build(componentDefinition);
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallableReferenceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallableReferenceImpl.java
new file mode 100644
index 0000000000..e674112a89
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallableReferenceImpl.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.component;
+
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.Conversation;
+
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Base class for implementations of service and callback references.
+ *
+ * @version $Rev$ $Date$
+ * @param <B> the type of the business interface
+ */
+public abstract class CallableReferenceImpl<B> implements CallableReference<B> {
+ private final Class<B> businessInterface;
+ private final ObjectFactory<B> factory;
+
+ protected CallableReferenceImpl(Class<B> businessInterface, ObjectFactory<B> factory) {
+ this.businessInterface = businessInterface;
+ this.factory = factory;
+ }
+
+ public B getService() {
+ return factory.getInstance();
+ }
+
+ public Class<B> getBusinessInterface() {
+ return businessInterface;
+ }
+
+ public boolean isConversational() {
+ return false;
+ }
+
+ public Conversation getConversation() {
+ return null;
+ }
+
+ public Object getCallbackID() {
+ return null;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallbackReferenceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallbackReferenceImpl.java
new file mode 100644
index 0000000000..532a8b2bad
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/CallbackReferenceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * 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.core.component;
+
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Default implementation of a callback reference.
+ *
+ * @version $Rev$ $Date$
+ * @param <CB> the type of the business interface
+ */
+public class CallbackReferenceImpl<CB> extends CallableReferenceImpl<CB> {
+ public CallbackReferenceImpl(Class<CB> businessInterface, ObjectFactory<CB> factory) {
+ super(businessInterface, factory);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java
new file mode 100644
index 0000000000..c2da089178
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java
@@ -0,0 +1,92 @@
+/*
+ * 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.core.component;
+
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.ServiceReference;
+import org.osoa.sca.ServiceRuntimeException;
+
+import org.apache.tuscany.api.TuscanyRuntimeException;
+
+/**
+ * Implementation of ComponentContext that delegates to a ComponentContextProvider.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentContextImpl implements ComponentContext {
+ private final ComponentContextProvider component;
+
+ public ComponentContextImpl(ComponentContextProvider component) {
+ this.component = component;
+ }
+
+ public String getURI() {
+ try {
+ return component.getUri().toString();
+ } catch (TuscanyRuntimeException e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ try {
+ return (R) component.cast(target);
+ } catch (TuscanyRuntimeException e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B> B getService(Class<B> businessInterface, String referenceName) {
+ try {
+ return component.getService(businessInterface, referenceName);
+ } catch (TuscanyRuntimeException e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) {
+ try {
+ return component.getServiceReference(businessInterface, referenceName);
+ } catch (TuscanyRuntimeException e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B> B getProperty(Class<B> type, String propertyName) {
+ try {
+ return component.getProperty(type, propertyName);
+ } catch (TuscanyRuntimeException e) {
+ throw new ServiceRuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) {
+ return null;
+ }
+
+ public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) {
+ return null;
+ }
+
+ public RequestContext getRequestContext() {
+ return null;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextProvider.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextProvider.java
new file mode 100644
index 0000000000..4237d8b09f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentContextProvider.java
@@ -0,0 +1,44 @@
+/*
+ * 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.core.component;
+
+import java.net.URI;
+
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.ServiceReference;
+import org.osoa.sca.CallableReference;
+
+/**
+ * Interface implemented by Component's that want to expose a ComponentContext.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ComponentContextProvider {
+ ComponentContext getComponentContext();
+
+ URI getUri();
+
+ <B> B getService(Class<B> businessInterface, String referenceName);
+
+ <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName);
+
+ <B> B getProperty(Class<B> type, String propertyName);
+
+ <B, R extends CallableReference<B>> R cast(B target);
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManager.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManager.java
new file mode 100644
index 0000000000..fcd1702bb3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManager.java
@@ -0,0 +1,86 @@
+/*
+ * 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.core.component;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.event.RuntimeEventListener;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+/**
+ * Responsible for tracking and managing the component tree for a runtime instance. The tree corresponds to components
+ * deployed to the current runtime and hence may be sparse in comparison to the assembly component hierarchy for the SCA
+ * domain as parents and children may be distributed to different runtimes.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ComponentManager extends RuntimeEventListener {
+
+ /**
+ * Registers a component which will be managed by the runtime
+ *
+ * @param component the component
+ * @throws RegistrationException
+ */
+ void register(Component component) throws RegistrationException;
+
+ /**
+ * Deregisters a component
+ *
+ * @param component the component to deregister
+ * @throws RegistrationException
+ */
+ void unregister(Component component) throws RegistrationException;
+
+ /**
+ * Register a simple Java Object as a system component. This is primarily intended for use by bootstrap code to
+ * create the initial configuration components.
+ *
+ * @param uri the uri of the resulting component
+ * @param service the service contract the component should expose
+ * @param instance the Object that will become the component's implementation
+ * @throws RegistrationException
+ */
+ <S, I extends S> void registerJavaObject(URI uri, ServiceContract<S> service, I instance)
+ throws RegistrationException;
+
+ /**
+ * Register a simple Java Object as a system component. This is primarily intended for use by bootstrap code to
+ * create the initial configuration components.
+ *
+ * @param uri the name of the resulting component
+ * @param services the service contracts the component should expose
+ * @param instance the Object that will become the component's implementation
+ * @throws RegistrationException
+ */
+ <S, I extends S> void registerJavaObject(URI uri, List<ServiceContract<?>> services, I instance)
+ throws RegistrationException;
+
+ /**
+ * Returns the component with the given URI
+ *
+ * @param uri the component URI
+ * @return the component or null if not found
+ */
+ Component getComponent(URI uri);
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManagerImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManagerImpl.java
new file mode 100644
index 0000000000..1c4f55332d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ComponentManagerImpl.java
@@ -0,0 +1,107 @@
+/*
+ * 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.core.component;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.DuplicateNameException;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.services.management.TuscanyManagementService;
+
+import org.apache.tuscany.core.resolver.AutowireResolver;
+
+/**
+ * Default implementation of the component manager
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentManagerImpl implements ComponentManager {
+ private TuscanyManagementService managementService;
+ private AutowireResolver resolver;
+ private Map<URI, Component> components;
+
+ public ComponentManagerImpl() {
+ components = new ConcurrentHashMap<URI, Component>();
+ }
+
+ public ComponentManagerImpl(TuscanyManagementService managementService, AutowireResolver resolver) {
+ this();
+ this.managementService = managementService;
+ this.resolver = resolver;
+ }
+
+ public synchronized void register(Component component) throws RegistrationException {
+ URI uri = component.getUri();
+ assert uri != null;
+ assert !uri.toString().endsWith("/");
+ if (components.containsKey(uri)) {
+ throw new DuplicateNameException(uri.toString());
+ }
+ components.put(uri, component);
+
+ if (managementService != null && component instanceof AtomicComponent) {
+ // FIXME shouldn't it take the canonical name and also not distinguish atomic components?
+ managementService.registerComponent(component.getUri().toString(), component);
+ }
+ }
+
+ public <S, I extends S> void registerJavaObject(URI uri, ServiceContract<S> service, I instance)
+ throws RegistrationException {
+ SystemSingletonAtomicComponent<S, I> component =
+ new SystemSingletonAtomicComponent<S, I>(uri, service, instance);
+ register(component);
+ if (resolver != null) {
+ for (ServiceContract contract : component.getServiceContracts()) {
+ resolver.addHostUri(contract, uri);
+ }
+ }
+ }
+
+ public <S, I extends S> void registerJavaObject(URI uri, List<ServiceContract<?>> services, I instance)
+ throws RegistrationException {
+ SystemSingletonAtomicComponent<S, I> component =
+ new SystemSingletonAtomicComponent<S, I>(uri, services, instance);
+ register(component);
+ if (resolver != null) {
+ for (ServiceContract contract : component.getServiceContracts()) {
+ resolver.addHostUri(contract, uri);
+ }
+ }
+ }
+
+ public synchronized void unregister(Component component) throws RegistrationException {
+ URI uri = component.getUri();
+ components.remove(uri);
+ }
+
+ public Component getComponent(URI name) {
+ return components.get(name);
+ }
+
+ public void onEvent(Event event) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/InstanceFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/InstanceFactory.java
new file mode 100644
index 0000000000..696db2ee2d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/InstanceFactory.java
@@ -0,0 +1,43 @@
+/*
+ * 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.core.component;
+
+import org.apache.tuscany.core.component.scope.InstanceWrapper;
+
+/**
+ * Interface for a factory that returns an injected component instance.
+ * This is used by a Component implementation to create new instances of
+ * application implementation objects as determined by the component scope's
+ * lifecycle.
+ * <p/>
+ * The implementation of this interface may be supplied by the user,
+ * may be generated during deployment, or may be dynamic.
+ *
+ * @version $Rev$ $Date$
+ * @param <T> Type of the instance generated by the factory.
+ */
+public interface InstanceFactory<T> {
+ /**
+ * Creates a new instance of the component.
+ * All injected values must be set but any @Init methods must not have been invoked.
+ *
+ * @return A wrapper for the created component instance.
+ */
+ InstanceWrapper<T> newInstance();
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java
new file mode 100644
index 0000000000..35125b85ef
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.component;
+
+/**
+ * Implementations enable lazy retrieval of a scope id associated with a request, i.e. an id (and presumably a context)
+ * do not have to be generated if the scope is never accessed. Identifiers are associated with the current request
+ * thread and keyed on scope type.
+ *
+ * @version $Rev$ $Date$
+ * @see org.apache.tuscany.spi.component.WorkContext
+ */
+public interface ScopeIdentifier {
+
+ /**
+ * Returns the scope id for the request.
+ */
+ Object getIdentifier();
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ServiceReferenceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ServiceReferenceImpl.java
new file mode 100644
index 0000000000..4d57d3efe0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/ServiceReferenceImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.component;
+
+import org.osoa.sca.ServiceReference;
+
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Default implementation of a ServiceReference.
+ *
+ * @version $Rev$ $Date$
+ * @param <B> the type of the business interface
+ */
+public class ServiceReferenceImpl<B> extends CallableReferenceImpl<B> implements ServiceReference<B> {
+ public ServiceReferenceImpl(Class<B> businessInterface, ObjectFactory<B> factory) {
+ super(businessInterface, factory);
+ }
+
+ public Object getConversationID() {
+ return null;
+ }
+
+ public void setConversationID(Object conversationId) throws IllegalStateException {
+ }
+
+ public void setCallbackID(Object callbackID) {
+ }
+
+ public Object getCallback() {
+ return null;
+ }
+
+ public void setCallback(Object callback) {
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/SystemSingletonAtomicComponent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/SystemSingletonAtomicComponent.java
new file mode 100644
index 0000000000..df2c88e2ea
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/SystemSingletonAtomicComponent.java
@@ -0,0 +1,134 @@
+/*
+ * 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.core.component;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetInitializationException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.extension.AbstractComponentExtension;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * An {@link org.apache.tuscany.spi.component.AtomicComponent} used when registering objects directly into a composite
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SystemSingletonAtomicComponent<S, T extends S> extends AbstractComponentExtension
+ implements AtomicComponent {
+ private T instance;
+ private List<ServiceContract> serviceContracts = new ArrayList<ServiceContract>();
+
+ public SystemSingletonAtomicComponent(URI name, ServiceContract<S> contract, T instance) {
+ super(name);
+ this.instance = instance;
+ this.serviceContracts.add(contract);
+ }
+
+ public SystemSingletonAtomicComponent(URI name, List<ServiceContract<?>> services, T instance) {
+ super(name);
+ this.instance = instance;
+ for (ServiceContract<?> contract : services) {
+ serviceContracts.add(contract);
+ }
+ }
+
+ public Scope getScope() {
+ return Scope.COMPOSITE;
+ }
+
+ public boolean isEagerInit() {
+ return false;
+ }
+
+ public boolean isDestroyable() {
+ return false;
+ }
+
+ public int getInitLevel() {
+ return 0;
+ }
+
+ public long getMaxIdleTime() {
+ return -1;
+ }
+
+ public long getMaxAge() {
+ return -1;
+ }
+
+ public T getTargetInstance() throws TargetResolutionException {
+ return instance;
+ }
+
+ public void init(Object instance) throws TargetInitializationException {
+
+ }
+
+ public void destroy(Object instance) throws TargetDestructionException {
+
+ }
+
+ public Object createInstance() throws ObjectCreationException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeInstance() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isOptimizable() {
+ return true;
+ }
+
+ public void attachWire(Wire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void attachWires(List<Wire> wires) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public List<Wire> getWires(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void attachCallbackWire(Wire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation) {
+ return null;
+ }
+
+ public List<ServiceContract> getServiceContracts() {
+ return serviceContracts;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java
new file mode 100644
index 0000000000..e7725307ff
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java
@@ -0,0 +1,212 @@
+/*
+ * 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.core.component;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.WorkContext;
+
+/**
+ * An implementation of an {@link org.apache.tuscany.spi.component.WorkContext} that handles event-to-thread
+ * associations using an <code>InheritableThreadLocal</code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class WorkContextImpl implements WorkContext {
+ private static final Object REMOTE_CONTEXT = new Object();
+ private static final Object CORRELATION_ID = new Object();
+ private static final Object CALLBACK_URIS = new Object();
+ private static final Object CURRENT_ATOMIC = new Object();
+ private static final Object CURRENT_SERVICE_NAMES = new Object();
+
+ // [rfeng] We cannot use InheritableThreadLocal for message ids here since it's shared by parent and children
+ private ThreadLocal<Map<Object, Object>> workContext = new ThreadLocal<Map<Object, Object>>();
+
+ // [rfeng] Session id requires InheritableThreadLocal
+ private ThreadLocal<Map<Object, Object>> inheritableContext = new InheritableThreadLocal<Map<Object, Object>>();
+
+ public WorkContextImpl() {
+ super();
+ }
+
+ public Object getCorrelationId() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return map.get(CORRELATION_ID);
+ }
+
+ public void setCorrelationId(Object id) {
+ Map<Object, Object> map = getWorkContextMap();
+ map.put(CORRELATION_ID, id);
+ }
+
+ public AtomicComponent getCurrentAtomicComponent() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return (AtomicComponent) map.get(CURRENT_ATOMIC);
+ }
+
+ public void setCurrentAtomicComponent(AtomicComponent component) {
+ Map<Object, Object> map = getWorkContextMap();
+ map.put(CURRENT_ATOMIC, component);
+ }
+
+ @SuppressWarnings("unchecked")
+ public LinkedList<URI> getCallbackUris() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return (LinkedList<URI>) map.get(CALLBACK_URIS);
+ }
+
+ public void setCallbackUris(LinkedList<URI> uris) {
+ Map<Object, Object> map = getWorkContextMap();
+ map.put(CALLBACK_URIS, uris);
+ }
+
+ public Component getRemoteComponent() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return (Component) map.get(REMOTE_CONTEXT);
+ }
+
+
+ public void setRemoteComponent(Component component) {
+ Map<Object, Object> map = getWorkContextMap();
+ map.put(REMOTE_CONTEXT, component);
+ }
+
+ public Object getIdentifier(Object type) {
+ Map<Object, Object> map = inheritableContext.get();
+ if (map == null) {
+ return null;
+ }
+ Object currentId = map.get(type);
+ if (currentId instanceof ScopeIdentifier) {
+ currentId = ((ScopeIdentifier) currentId).getIdentifier();
+ // once we have accessed the id, replace the lazy wrapper
+ map.put(type, currentId);
+ }
+ return currentId;
+ }
+
+ public void setIdentifier(Object type, Object identifier) {
+ Map<Object, Object> map = inheritableContext.get();
+ if (map == null) {
+ map = new IdentityHashMap<Object, Object>();
+ inheritableContext.set(map);
+ }
+ map.put(type, identifier);
+ }
+
+ public void clearIdentifier(Object type) {
+ if (type == null) {
+ return;
+ }
+ Map map = inheritableContext.get();
+ if (map != null) {
+ map.remove(type);
+ }
+ }
+
+ public void clearIdentifiers() {
+ inheritableContext.remove();
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public String popServiceName() {
+ Map<Object, Object> map = inheritableContext.get();
+ if (map == null) {
+ return null;
+ }
+ List<String> stack = (List) map.get(CURRENT_SERVICE_NAMES);
+ if (stack == null || stack.size() < 1) {
+ return null;
+ }
+ String name = stack.remove(stack.size() - 1);
+ if (stack.size() == 0) {
+ // cleanup to avoid leaks
+ map.remove(CURRENT_SERVICE_NAMES);
+ }
+ return name;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public String getCurrentServiceName() {
+ Map<Object, Object> map = inheritableContext.get();
+ if (map == null) {
+ return null;
+ }
+ List<String> stack = (List) map.get(CURRENT_SERVICE_NAMES);
+ if (stack == null || stack.size() < 1) {
+ return null;
+ }
+ return stack.get(stack.size() - 1);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public void pushServiceName(String name) {
+ Map<Object, Object> map = inheritableContext.get();
+ List<String> names;
+ if (map == null) {
+ map = new IdentityHashMap<Object, Object>();
+ inheritableContext.set(map);
+ names = new ArrayList<String>();
+ map.put(CURRENT_SERVICE_NAMES, names);
+ } else {
+ names = (List<String>) map.get(CURRENT_SERVICE_NAMES);
+ if (names == null) {
+ names = new ArrayList<String>();
+ map.put(CURRENT_SERVICE_NAMES, names);
+ }
+ }
+ names.add(name);
+ }
+
+ public void clearServiceNames() {
+ Map<Object, Object> map = inheritableContext.get();
+ if (map == null) {
+ return;
+ }
+ map.remove(CURRENT_SERVICE_NAMES);
+ }
+
+ private Map<Object, Object> getWorkContextMap() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ map = new IdentityHashMap<Object, Object>();
+ workContext.set(map);
+ }
+ return map;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java
new file mode 100644
index 0000000000..6d026ca08c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.component.event;
+
+import org.apache.tuscany.spi.event.Event;
+
+/**
+ * A basic implementation of a runtime event
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public abstract class AbstractEvent implements Event {
+ protected Object source;
+
+ public AbstractEvent(Object source) {
+ assert source != null : "Source id was null";
+ this.source = source;
+ }
+
+ public Object getSource() {
+ return source;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java
new file mode 100644
index 0000000000..762b917600
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Base implementation of a request event
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public abstract class AbstractRequestEvent extends AbstractEvent implements RequestEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ */
+ public AbstractRequestEvent(Object source) {
+ super(source);
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentEvent.java
new file mode 100644
index 0000000000..7de32a56d0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentEvent.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.component.event;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.event.Event;
+
+/**
+ * Implemented by runtime events associated with a component, e.g. lifecycle events
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public interface ComponentEvent extends Event {
+
+ URI getComponentUri();
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStart.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStart.java
new file mode 100644
index 0000000000..6be1c88d3f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStart.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.core.component.event;
+
+import java.net.URI;
+
+/**
+ * Propagated when a component starts
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class ComponentStart extends AbstractEvent implements ComponentEvent {
+
+ private URI uri;
+
+ /**
+ * Creates a component start event
+ *
+ * @param source the source of the event
+ * @param componentURI the uri of the component being started
+ */
+ public ComponentStart(Object source, URI componentURI) {
+ super(source);
+ this.uri = componentURI;
+ }
+
+ public URI getComponentUri() {
+ return uri;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStop.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStop.java
new file mode 100644
index 0000000000..ac0a7fd5c0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ComponentStop.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.component.event;
+
+import java.net.URI;
+
+/**
+ * Propagated when a component stops
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class ComponentStop extends AbstractEvent implements ComponentEvent {
+
+ private URI uri;
+
+ /**
+ * Creates a component stop event
+ *
+ * @param source the source of the event
+ * @param componentUri the composite component associated the component being stopped
+ */
+ public ComponentStop(Object source, URI componentUri) {
+ super(source);
+ this.uri = componentUri;
+ }
+
+ public URI getComponentUri() {
+ return uri;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java
new file mode 100644
index 0000000000..4a51d970c3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java
@@ -0,0 +1,31 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when a conversation session is expired
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class ConversationEnd extends ConversationalEvent {
+
+ public ConversationEnd(Object source, Object id) {
+ super(source, id);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java
new file mode 100644
index 0000000000..5725369bf6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java
@@ -0,0 +1,31 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when a conversation session has started
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class ConversationStart extends ConversationalEvent {
+
+ public ConversationStart(Object source, Object id) {
+ super(source, id);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java
new file mode 100644
index 0000000000..a75086e745
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * A base implementation of conversational session events in the runtime
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class ConversationalEvent extends AbstractEvent {
+
+ private Object id;
+
+ public ConversationalEvent(Object source, Object id) {
+ super(source);
+ assert id != null : "Conversation id was null";
+ this.id = id;
+ }
+
+ public Object getId() {
+ return id;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java
new file mode 100644
index 0000000000..01bd769031
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when an HTTP-based request has ended.
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class HttpRequestEnded extends HttpSessionEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ * @param id the id of the HTTP session being ended
+ */
+ public HttpRequestEnded(Object source, Object id) {
+ super(source, id);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java
new file mode 100644
index 0000000000..9d0ff80dd7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when an HTTP-based request has started
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class HttpRequestStart extends HttpSessionEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ * @param id the id of the HTTP session being ended
+ */
+ public HttpRequestStart(Object source, Object id) {
+ super(source, id);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java
new file mode 100644
index 0000000000..7f2bebe94a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when an HTTP-based session is expired
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class HttpSessionEnd extends HttpSessionEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ * @param id the id of the HTTP session being ended
+ */
+ public HttpSessionEnd(Object source, Object id) {
+ super(source, id);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java
new file mode 100644
index 0000000000..ed245d0930
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java
@@ -0,0 +1,45 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * A base implementation of HTTP-based session events in the runtime
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public abstract class HttpSessionEvent extends AbstractEvent {
+
+ private Object id;
+
+ public HttpSessionEvent(Object source, Object id) {
+ super(source);
+ assert id != null : "Session id was null";
+ this.id = id;
+ }
+
+
+ public Object getSource() {
+ return source;
+ }
+
+ public Object getId() {
+ return id;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java
new file mode 100644
index 0000000000..7f9c0fadea
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when an HTTP-based session has started
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class HttpSessionStart extends HttpSessionEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ * @param id the id of the HTTP session being ended
+ */
+ public HttpSessionStart(Object source, Object id) {
+ super(source, id);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java
new file mode 100644
index 0000000000..25856e86f8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when a request completes or is ended
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class RequestEnd extends AbstractRequestEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ */
+ public RequestEnd(Object source) {
+ super(source);
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java
new file mode 100644
index 0000000000..9a6d767236
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java
@@ -0,0 +1,28 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Implemented by runtime events associated request
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public interface RequestEvent {
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java
new file mode 100644
index 0000000000..466f52551a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.component.event;
+
+/**
+ * Propagated when a request is started in the runtime
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class RequestStart extends AbstractRequestEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ */
+ public RequestStart(Object source) {
+ super(source);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java
new file mode 100644
index 0000000000..7f1d507a1b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java
@@ -0,0 +1,158 @@
+/*
+ * 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.core.component.scope;
+
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.tuscany.spi.AbstractLifecycle;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.PersistenceException;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.TargetNotFoundException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.event.EventFilter;
+import org.apache.tuscany.spi.event.RuntimeEventListener;
+import org.apache.tuscany.spi.event.TrueFilter;
+
+/**
+ * Implements functionality common to scope contexts.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractScopeContainer extends AbstractLifecycle implements ScopeContainer {
+ private static final EventFilter TRUE_FILTER = new TrueFilter();
+
+ protected WorkContext workContext;
+ protected ScopeContainerMonitor monitor;
+ private Map<EventFilter, List<RuntimeEventListener>> listeners;
+
+ public AbstractScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) {
+ this.workContext = workContext;
+ this.monitor = monitor;
+ }
+
+ public void addListener(RuntimeEventListener listener) {
+ addListener(TRUE_FILTER, listener);
+ }
+
+ public void removeListener(RuntimeEventListener listener) {
+ assert listener != null;
+ synchronized (getListeners()) {
+ for (List<RuntimeEventListener> currentList : getListeners().values()) {
+ for (RuntimeEventListener current : currentList) {
+ if (current == listener) {
+ currentList.remove(current);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ public void addListener(EventFilter filter, RuntimeEventListener listener) {
+ assert listener != null;
+ synchronized (getListeners()) {
+ List<RuntimeEventListener> list = getListeners().get(filter);
+ if (list == null) {
+ list = new CopyOnWriteArrayList<RuntimeEventListener>();
+ listeners.put(filter, list);
+ }
+ list.add(listener);
+ }
+ }
+
+ public void publish(Event event) {
+ assert event != null;
+ for (Map.Entry<EventFilter, List<RuntimeEventListener>> entry : getListeners().entrySet()) {
+ if (entry.getKey().match(event)) {
+ for (RuntimeEventListener listener : entry.getValue()) {
+ listener.onEvent(event);
+ }
+ }
+ }
+ }
+
+ public Object getInstance(AtomicComponent component) throws TargetResolutionException {
+ InstanceWrapper ctx = getInstanceWrapper(component, true);
+ if (ctx != null) {
+ if (!ctx.isStarted()) {
+ ctx.start();
+ }
+ return ctx.getInstance();
+ }
+ return null;
+ }
+
+ public Object getAssociatedInstance(AtomicComponent component) throws TargetResolutionException {
+ InstanceWrapper ctx = getInstanceWrapper(component, false);
+ if (ctx != null) {
+ if (!ctx.isStarted()) {
+ ctx.start();
+ }
+ return ctx.getInstance();
+ }
+ throw new TargetNotFoundException(component.getUri().toString());
+ }
+
+ public void persistNew(AtomicComponent component, String id, Object instance, long expiration)
+ throws PersistenceException {
+ throw new UnsupportedOperationException("Scope does not support persistence");
+
+ }
+
+ public void persist(AtomicComponent component, String id, Object instance, long expiration)
+ throws PersistenceException {
+ throw new UnsupportedOperationException("Scope does not support persistence");
+ }
+
+ public void remove(AtomicComponent component) throws PersistenceException {
+ throw new UnsupportedOperationException("Scope does not support persistence");
+ }
+
+ protected Map<EventFilter, List<RuntimeEventListener>> getListeners() {
+ if (listeners == null) {
+ listeners = new ConcurrentHashMap<EventFilter, List<RuntimeEventListener>>();
+ }
+ return listeners;
+ }
+
+ protected void checkInit() {
+ if (getLifecycleState() != RUNNING) {
+ throw new IllegalStateException("Scope container not running [" + getLifecycleState() + "]");
+ }
+ }
+
+ protected WorkContext getWorkContext() {
+ return workContext;
+ }
+
+ public String toString() {
+ return "In state [" + super.toString() + ']';
+ }
+
+ protected abstract InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create)
+ throws TargetResolutionException;
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java
new file mode 100644
index 0000000000..623704fbee
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java
@@ -0,0 +1,184 @@
+/*
+ * 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.core.component.scope;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetInitializationException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.core.component.event.ComponentStart;
+import org.apache.tuscany.core.component.event.ComponentStop;
+
+/**
+ * A scope context which manages atomic component instances keyed by composite
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeScopeContainer extends AbstractScopeContainer {
+ private static final InstanceWrapper EMPTY = new EmptyWrapper();
+ private static final ComponentInitComparator COMPARATOR = new ComponentInitComparator();
+
+ private final Map<AtomicComponent, InstanceWrapper> instanceWrappers;
+ // the queue of instanceWrappers to destroy, in the order that their instances were created
+ private final List<InstanceWrapper> destroyQueue;
+
+ public CompositeScopeContainer(ScopeContainerMonitor monitor) {
+ super(null, monitor);
+ instanceWrappers = new ConcurrentHashMap<AtomicComponent, InstanceWrapper>();
+ destroyQueue = new ArrayList<InstanceWrapper>();
+ }
+
+ public Scope getScope() {
+ return Scope.COMPOSITE;
+ }
+
+ public void onEvent(Event event) {
+ checkInit();
+ if (event instanceof ComponentStart) {
+ try {
+ eagerInitComponents();
+ } catch (ObjectCreationException e) {
+ monitor.eagerInitializationError(e);
+ } catch (TargetResolutionException e) {
+ monitor.eagerInitializationError(e);
+ }
+ lifecycleState = RUNNING;
+ } else if (event instanceof ComponentStop) {
+ shutdownContexts();
+ }
+ }
+
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ public synchronized void stop() {
+ checkInit();
+ instanceWrappers.clear();
+ synchronized (destroyQueue) {
+ destroyQueue.clear();
+ }
+ lifecycleState = STOPPED;
+ }
+
+ /**
+ * Notifies instanceWrappers of a shutdown in reverse order to which they were started
+ */
+ private void shutdownContexts() {
+ if (destroyQueue.size() == 0) {
+ return;
+ }
+ synchronized (destroyQueue) {
+ // shutdown destroyable instances in reverse instantiation order
+ ListIterator<InstanceWrapper> iter = destroyQueue.listIterator(destroyQueue.size());
+ while (iter.hasPrevious()) {
+ try {
+ iter.previous().stop();
+ } catch (TargetDestructionException e) {
+ monitor.destructionError(e);
+ }
+ }
+ destroyQueue.clear();
+ }
+ }
+
+ public void register(AtomicComponent component) {
+ checkInit();
+ instanceWrappers.put(component, EMPTY);
+ }
+
+ protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create)
+ throws TargetResolutionException {
+ checkInit();
+ InstanceWrapper ctx = instanceWrappers.get(component);
+ assert ctx != null;
+ if (ctx == EMPTY && !create) {
+ return null;
+ }
+ if (ctx == EMPTY) {
+ ctx = new InstanceWrapperImpl(component, component.createInstance());
+ ctx.start();
+ instanceWrappers.put(component, ctx);
+ synchronized (destroyQueue) {
+ destroyQueue.add(ctx);
+ }
+ }
+ return ctx;
+ }
+
+ private void eagerInitComponents() throws ObjectCreationException, TargetResolutionException {
+ List<AtomicComponent> componentList = new ArrayList<AtomicComponent>(instanceWrappers.keySet());
+ Collections.sort(componentList, COMPARATOR);
+ // start each group
+ for (AtomicComponent component : componentList) {
+ if (component.getInitLevel() <= 0) {
+ // Don't eagerly init
+ continue;
+ }
+ // the instance could have been created from a depth-first traversal
+ InstanceWrapper ctx = instanceWrappers.get(component);
+ if (ctx == EMPTY) {
+ ctx = new InstanceWrapperImpl(component, component.createInstance());
+ ctx.start();
+ instanceWrappers.put(component, ctx);
+ destroyQueue.add(ctx);
+ }
+ }
+ }
+
+ private static class ComponentInitComparator implements Comparator<AtomicComponent> {
+ public int compare(AtomicComponent o1, AtomicComponent o2) {
+ return o1.getInitLevel() - o2.getInitLevel();
+ }
+ }
+
+ private static class EmptyWrapper implements InstanceWrapper {
+ public Object getInstance() {
+ return null;
+ }
+
+ public boolean isStarted() {
+ return true;
+ }
+
+ public void start() throws TargetInitializationException {
+
+ }
+
+ public void stop() throws TargetDestructionException {
+
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java
new file mode 100644
index 0000000000..fc89bbc609
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.component.scope;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.api.annotation.Monitor;
+
+/**
+ * Creates a new composite scope context
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+@EagerInit
+public class CompositeScopeObjectFactory implements ObjectFactory<CompositeScopeContainer> {
+ private ScopeContainerMonitor monitor;
+
+ public CompositeScopeObjectFactory(@Reference ScopeRegistry registry,
+ @Monitor ScopeContainerMonitor monitor) {
+ registry.registerFactory(Scope.COMPOSITE, this);
+ this.monitor = monitor;
+ }
+
+ public CompositeScopeContainer getInstance() throws ObjectCreationException {
+ return new CompositeScopeContainer(monitor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java
new file mode 100644
index 0000000000..eb4a06602f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java
@@ -0,0 +1,217 @@
+/*
+ * 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.core.component.scope;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.PersistenceException;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetNotFoundException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.event.RuntimeEventListener;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.services.store.Store;
+import org.apache.tuscany.spi.services.store.StoreExpirationEvent;
+import org.apache.tuscany.spi.services.store.StoreReadException;
+import org.apache.tuscany.spi.services.store.StoreWriteException;
+
+/**
+ * A scope context which manages atomic component instances keyed on a conversation session
+ *
+ * @version $Rev: 452655 $ $Date: 2006-10-03 18:09:02 -0400 (Tue, 03 Oct 2006) $
+ */
+public class ConversationalScopeContainer extends AbstractScopeContainer implements ScopeContainer {
+ private Store nonDurableStore;
+ private Map<AtomicComponent, AtomicComponent> components;
+
+ public ConversationalScopeContainer(Store store, WorkContext workContext, final ScopeContainerMonitor monitor) {
+ super(workContext, monitor);
+ this.nonDurableStore = store;
+ if (store != null) {
+ store.addListener(new ExpirationListener(monitor));
+ }
+ components = new ConcurrentHashMap<AtomicComponent, AtomicComponent>();
+ }
+
+ public Scope getScope() {
+ return Scope.CONVERSATION;
+ }
+
+ public void onEvent(Event event) {
+ checkInit();
+ }
+
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ public synchronized void stop() {
+ lifecycleState = STOPPED;
+ }
+
+ public void register(AtomicComponent component) {
+ components.put(component, component);
+ component.addListener(this);
+ }
+
+ @Override
+ public Object getInstance(AtomicComponent component) throws TargetResolutionException {
+ String conversationId = getConversationId();
+ try {
+ workContext.setCurrentAtomicComponent(component);
+ Object instance = nonDurableStore.readRecord(component, conversationId);
+ if (instance != null) {
+ if (component.getMaxIdleTime() > 0) {
+ // update expiration
+ long expire = System.currentTimeMillis() + component.getMaxIdleTime();
+ nonDurableStore.updateRecord(component, conversationId, instance, expire);
+ }
+ } else {
+ instance = component.createInstance();
+ long expire = calculateExpiration(component);
+ nonDurableStore.insertRecord(component, conversationId, instance, expire);
+ component.init(instance);
+ }
+ return instance;
+ } catch (StoreReadException e) {
+ throw new TargetResolutionException("Error retrieving target instance", e);
+ } catch (StoreWriteException e) {
+ throw new TargetResolutionException("Error persisting target instance", e);
+ } finally {
+ workContext.setCurrentAtomicComponent(null);
+ }
+ }
+
+ public Object getAssociatedInstance(AtomicComponent component) throws TargetResolutionException {
+ String conversationId = getConversationId();
+ try {
+ workContext.setCurrentAtomicComponent(component);
+ Object instance = nonDurableStore.readRecord(component, conversationId);
+ if (instance != null) {
+ if (component.getMaxIdleTime() > 0) {
+ // update expiration
+ long expire = System.currentTimeMillis() + component.getMaxIdleTime();
+ nonDurableStore.updateRecord(component, conversationId, instance, expire);
+ }
+ return instance;
+ } else {
+ throw new TargetNotFoundException(component.getUri().toString());
+ }
+ } catch (StoreReadException e) {
+ throw new TargetResolutionException("Error retrieving target instance", e);
+ } catch (StoreWriteException e) {
+ throw new TargetResolutionException("Error persisting target instance", e);
+ } finally {
+ workContext.setCurrentAtomicComponent(null);
+ }
+ }
+
+ public void persistNew(AtomicComponent component, String id, Object instance, long expiration)
+ throws PersistenceException {
+ try {
+ nonDurableStore.insertRecord(component, id, instance, expiration);
+ } catch (StoreWriteException e) {
+ throw new PersistenceException(e);
+ }
+ }
+
+ public void persist(AtomicComponent component, String id, Object instance, long expiration)
+ throws PersistenceException {
+ try {
+ nonDurableStore.updateRecord(component, id, instance, expiration);
+ } catch (StoreWriteException e) {
+ throw new PersistenceException(e);
+ }
+ }
+
+ public void remove(AtomicComponent component) throws PersistenceException {
+ String conversationId = getConversationId();
+ try {
+ workContext.setCurrentAtomicComponent(component);
+ Object instance = nonDurableStore.readRecord(component, conversationId);
+ if (instance != null) {
+ nonDurableStore.removeRecord(component, conversationId);
+ }
+ } catch (StoreReadException e) {
+ throw new PersistenceException(e);
+ } catch (StoreWriteException e) {
+ throw new PersistenceException(e);
+ }
+ }
+
+ protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the conversation id associated with the current invocation context
+ */
+ private String getConversationId() {
+ String conversationId = (String) workContext.getIdentifier(Scope.CONVERSATION);
+ assert conversationId != null;
+ return conversationId;
+ }
+
+ private long calculateExpiration(AtomicComponent component) {
+ if (component.getMaxAge() > 0) {
+ long now = System.currentTimeMillis();
+ return now + component.getMaxAge();
+ } else if (component.getMaxIdleTime() > 0) {
+ long now = System.currentTimeMillis();
+ return now + component.getMaxIdleTime();
+ } else {
+ return Store.DEFAULT_EXPIRATION_OFFSET;
+ }
+ }
+
+ /**
+ * Receives expiration events from the store and notifies the corresponding atomic component
+ */
+ private static class ExpirationListener implements RuntimeEventListener {
+ private final ScopeContainerMonitor monitor;
+
+ public ExpirationListener(ScopeContainerMonitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public void onEvent(Event event) {
+ if (event instanceof StoreExpirationEvent) {
+ StoreExpirationEvent expiration = (StoreExpirationEvent) event;
+ SCAObject object = expiration.getOwner();
+ assert object instanceof AtomicComponent;
+ AtomicComponent owner = (AtomicComponent) object;
+ try {
+ owner.destroy(expiration.getInstance());
+ } catch (TargetDestructionException e) {
+ monitor.destructionError(e);
+ }
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java
new file mode 100644
index 0000000000..30a4487215
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java
@@ -0,0 +1,58 @@
+/*
+ * 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.core.component.scope;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.services.store.Store;
+
+import org.apache.tuscany.api.annotation.Monitor;
+
+/**
+ * Creates a new Session Scope context
+ *
+ * @version $$Rev: 450456 $$ $$Date: 2006-09-27 10:28:36 -0400 (Wed, 27 Sep 2006) $$
+ */
+@EagerInit
+public class ConversationalScopeObjectFactory implements ObjectFactory<ConversationalScopeContainer> {
+ private WorkContext context;
+ private Store store;
+ private ScopeContainerMonitor monitor;
+
+ public ConversationalScopeObjectFactory(@Reference ScopeRegistry registry,
+ @Reference WorkContext context,
+ @Reference Store store,
+ @Monitor ScopeContainerMonitor monitor) {
+ registry.registerFactory(Scope.CONVERSATION, this);
+ this.context = context;
+ this.store = store;
+ this.monitor = monitor;
+ }
+
+ public ConversationalScopeContainer getInstance() throws ObjectCreationException {
+ return new ConversationalScopeContainer(store, context, monitor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java
new file mode 100644
index 0000000000..83c79b2367
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java
@@ -0,0 +1,135 @@
+/*
+ * 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.core.component.scope;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.core.component.event.HttpSessionEnd;
+
+/**
+ * A scope context which manages atomic component instances keyed on HTTP session
+ *
+ * @version $Rev$ $Date$
+ */
+public class HttpSessionScopeContainer extends AbstractScopeContainer {
+ private final Map<AtomicComponent, Map<Object, InstanceWrapper>> contexts;
+ private final Map<Object, List<InstanceWrapper>> destroyQueues;
+
+ public HttpSessionScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) {
+ super(workContext, monitor);
+ contexts = new ConcurrentHashMap<AtomicComponent, Map<Object, InstanceWrapper>>();
+ destroyQueues = new ConcurrentHashMap<Object, List<InstanceWrapper>>();
+ }
+
+ public Scope getScope() {
+ return Scope.SESSION;
+ }
+
+ public void onEvent(Event event) {
+ checkInit();
+ if (event instanceof HttpSessionEnd) {
+ Object key = ((HttpSessionEnd) event).getId();
+ shutdownInstances(key);
+ workContext.clearIdentifier(key);
+ }
+ }
+
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ public synchronized void stop() {
+ contexts.clear();
+ synchronized (destroyQueues) {
+ destroyQueues.clear();
+ }
+ lifecycleState = STOPPED;
+ }
+
+ public void register(AtomicComponent component) {
+ contexts.put(component, new ConcurrentHashMap<Object, InstanceWrapper>());
+ component.addListener(this);
+ }
+
+ protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create)
+ throws TargetResolutionException {
+ Object key = workContext.getIdentifier(Scope.SESSION);
+ assert key != null : "HTTP session key not bound in work context";
+ return getInstance(component, key, create);
+ }
+
+ private InstanceWrapper getInstance(AtomicComponent component, Object key, boolean create)
+ throws TargetResolutionException {
+ Map<Object, InstanceWrapper> wrappers = contexts.get(component);
+ InstanceWrapper ctx = wrappers.get(key);
+ if (ctx == null && !create) {
+ return null;
+ }
+ if (ctx == null) {
+ ctx = new InstanceWrapperImpl(component, component.createInstance());
+ ctx.start();
+ wrappers.put(key, ctx);
+ List<InstanceWrapper> destroyQueue = destroyQueues.get(key);
+ if (destroyQueue == null) {
+ destroyQueue = new ArrayList<InstanceWrapper>();
+ destroyQueues.put(key, destroyQueue);
+ }
+ synchronized (destroyQueue) {
+ destroyQueue.add(ctx);
+ }
+ }
+ return ctx;
+
+ }
+
+ private void shutdownInstances(Object key) {
+ List<InstanceWrapper> destroyQueue = destroyQueues.remove(key);
+ if (destroyQueue != null) {
+ for (Map<Object, InstanceWrapper> map : contexts.values()) {
+ map.remove(key);
+ }
+ ListIterator<InstanceWrapper> iter = destroyQueue.listIterator(destroyQueue.size());
+ synchronized (destroyQueue) {
+ while (iter.hasPrevious()) {
+ try {
+ iter.previous().stop();
+ } catch (TargetDestructionException e) {
+ monitor.destructionError(e);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java
new file mode 100644
index 0000000000..5fae335e6b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.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.core.component.scope;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.api.annotation.Monitor;
+
+/**
+ * Creates a new HTTP session scope context
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+@EagerInit
+public class HttpSessionScopeObjectFactory implements ObjectFactory<HttpSessionScopeContainer> {
+ private WorkContext context;
+ private ScopeContainerMonitor monitor;
+
+ public HttpSessionScopeObjectFactory(@Reference ScopeRegistry registry,
+ @Reference WorkContext context,
+ @Monitor ScopeContainerMonitor monitor) {
+ registry.registerFactory(Scope.SESSION, this);
+ this.context = context;
+ this.monitor = monitor;
+ }
+
+ public HttpSessionScopeContainer getInstance() throws ObjectCreationException {
+ return new HttpSessionScopeContainer(context, monitor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java
new file mode 100644
index 0000000000..121a6d3b70
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.component.scope;
+
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetInitializationException;
+
+/**
+ * Provides lifecycle management for an implementation instance associated with an {@link
+ * org.apache.tuscany.spi.component.AtomicComponent} for use by the atomic component's associated {@link
+ * org.apache.tuscany.spi.component.ScopeContainer}
+ *
+ * @version $Rev$ $Date$
+ */
+public interface InstanceWrapper<T> {
+
+ T getInstance();
+
+ boolean isStarted();
+
+ void start() throws TargetInitializationException;
+
+ void stop() throws TargetDestructionException;
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperBase.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperBase.java
new file mode 100644
index 0000000000..e52b20fe84
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperBase.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.component.scope;
+
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetInitializationException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class InstanceWrapperBase<T> implements InstanceWrapper<T> {
+ protected final T instance;
+ private boolean started;
+
+ public InstanceWrapperBase(T instance) {
+ assert instance != null;
+ this.instance = instance;
+ }
+
+ public T getInstance() {
+ assert started;
+ return instance;
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public void start() throws TargetInitializationException {
+ started = true;
+ }
+
+ public void stop() throws TargetDestructionException {
+ started = false;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java
new file mode 100644
index 0000000000..200f9a6e6d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.component.scope;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetInitializationException;
+
+/**
+ * Default implementation of an <code>InstanceWrapper</code>
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class InstanceWrapperImpl extends InstanceWrapperBase<Object> {
+ private AtomicComponent component;
+
+ public InstanceWrapperImpl(AtomicComponent component, Object instance) {
+ super(instance);
+ assert component != null;
+ this.component = component;
+ }
+
+ public void start() throws TargetInitializationException {
+ component.init(instance);
+ super.start();
+ }
+
+ public void stop() throws TargetDestructionException {
+ super.stop();
+ component.destroy(instance);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java
new file mode 100644
index 0000000000..22beaae740
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java
@@ -0,0 +1,126 @@
+/*
+ * 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.core.component.scope;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.core.component.event.RequestEnd;
+
+/**
+ * A scope context which manages atomic component instances keyed on the current request context
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeContainer extends AbstractScopeContainer {
+ private final Map<AtomicComponent, Map<Thread, InstanceWrapper>> contexts;
+ private final Map<Thread, List<InstanceWrapper>> destroyQueues;
+
+ public RequestScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) {
+ super(workContext, monitor);
+ contexts = new ConcurrentHashMap<AtomicComponent, Map<Thread, InstanceWrapper>>();
+ destroyQueues = new ConcurrentHashMap<Thread, List<InstanceWrapper>>();
+ }
+
+ public Scope getScope() {
+ return Scope.REQUEST;
+ }
+
+ public void onEvent(Event event) {
+ checkInit();
+ if (event instanceof RequestEnd) {
+ shutdownInstances(Thread.currentThread());
+ }
+ }
+
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ public synchronized void stop() {
+ contexts.clear();
+ synchronized (destroyQueues) {
+ destroyQueues.clear();
+ }
+ lifecycleState = STOPPED;
+ }
+
+ public void register(AtomicComponent component) {
+ contexts.put(component, new ConcurrentHashMap<Thread, InstanceWrapper>());
+ }
+
+ protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create)
+ throws TargetResolutionException {
+ Map<Thread, InstanceWrapper> instanceContextMap = contexts.get(component);
+ assert instanceContextMap != null : "Atomic component not registered";
+ InstanceWrapper ctx = instanceContextMap.get(Thread.currentThread());
+ if (ctx == null && !create) {
+ return null;
+ }
+ if (ctx == null) {
+ ctx = new InstanceWrapperImpl(component, component.createInstance());
+ ctx.start();
+ instanceContextMap.put(Thread.currentThread(), ctx);
+ List<InstanceWrapper> destroyQueue = destroyQueues.get(Thread.currentThread());
+ if (destroyQueue == null) {
+ destroyQueue = new ArrayList<InstanceWrapper>();
+ destroyQueues.put(Thread.currentThread(), destroyQueue);
+ }
+ synchronized (destroyQueue) {
+ destroyQueue.add(ctx);
+ }
+ }
+ return ctx;
+ }
+
+ private void shutdownInstances(Thread key) {
+ List<InstanceWrapper> destroyQueue = destroyQueues.remove(key);
+ if (destroyQueue != null && destroyQueue.size() > 0) {
+ Thread thread = Thread.currentThread();
+ for (Map<Thread, InstanceWrapper> map : contexts.values()) {
+ map.remove(thread);
+ }
+ ListIterator<InstanceWrapper> iter = destroyQueue.listIterator(destroyQueue.size());
+ synchronized (destroyQueue) {
+ while (iter.hasPrevious()) {
+ try {
+ iter.previous().stop();
+ } catch (TargetDestructionException e) {
+ monitor.destructionError(e);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java
new file mode 100644
index 0000000000..7ad2603eeb
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.component.scope;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.WorkContext;
+
+import org.apache.tuscany.api.annotation.Monitor;
+
+/**
+ * Creates a new request scope context
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class RequestScopeObjectFactory implements ObjectFactory<RequestScopeContainer> {
+ private WorkContext context;
+ private ScopeContainerMonitor monitor;
+
+
+ public RequestScopeObjectFactory(@Reference WorkContext context, @Monitor ScopeContainerMonitor monitor) {
+ this.context = context;
+ this.monitor = monitor;
+ }
+
+ public RequestScopeContainer getInstance() throws ObjectCreationException {
+ return new RequestScopeContainer(context, monitor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java
new file mode 100644
index 0000000000..da338dd0ef
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core.component.scope;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.model.Scope;
+
+/**
+ * The default implementation of a scope registry
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeRegistryImpl implements ScopeRegistry {
+ private final Map<Scope, ScopeContainer> scopeCache =
+ new ConcurrentHashMap<Scope, ScopeContainer>();
+ private final Map<Scope, ObjectFactory<? extends ScopeContainer>> factoryCache =
+ new ConcurrentHashMap<Scope, ObjectFactory<? extends ScopeContainer>>();
+
+ public ScopeContainer getScopeContainer(Scope scope) {
+ assert Scope.COMPOSITE != scope;
+ ScopeContainer container = scopeCache.get(scope);
+ if (container == null) {
+ ObjectFactory<? extends ScopeContainer> factory = factoryCache.get(scope);
+ if (factory != null) {
+ container = factory.getInstance();
+ container.start();
+ scopeCache.put(scope, container);
+ }
+ }
+ return container;
+ }
+
+ public <T extends ScopeContainer> void registerFactory(Scope scope, ObjectFactory<T> factory) {
+ factoryCache.put(scope, factory);
+ }
+
+ public void deregisterFactory(Scope scope) {
+ factoryCache.remove(scope);
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java
new file mode 100644
index 0000000000..cbd47b6cdd
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.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.core.component.scope;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.model.Scope;
+
+/**
+ * A scope context which manages stateless atomic component instances in a non-pooled fashion
+ *
+ * @version $Rev$ $Date$
+ */
+public class StatelessScopeContainer extends AbstractScopeContainer {
+
+ public StatelessScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) {
+ super(workContext, monitor);
+ }
+
+ public Scope getScope() {
+ return Scope.STATELESS;
+ }
+
+ public synchronized void start() {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]");
+ }
+ lifecycleState = RUNNING;
+ }
+
+ public synchronized void stop() {
+ if (lifecycleState != RUNNING) {
+ throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]");
+ }
+ lifecycleState = STOPPED;
+ }
+
+ public void onEvent(Event event) {
+ }
+
+ public void register(AtomicComponent component) {
+ checkInit();
+ }
+
+ protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create)
+ throws TargetResolutionException {
+ // there never is a previously associated instance, return null
+ if (!create) {
+ return null;
+ }
+ InstanceWrapper ctx = new InstanceWrapperImpl(component, component.createInstance());
+ ctx.start();
+ return ctx;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java
new file mode 100644
index 0000000000..1522f6c528
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.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.core.component.scope;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.api.annotation.Monitor;
+
+/**
+ * Creates a new stateless scope context
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+@EagerInit
+public class StatelessScopeObjectFactory implements ObjectFactory<StatelessScopeContainer> {
+ private WorkContext context;
+ private ScopeContainerMonitor monitor;
+
+ public StatelessScopeObjectFactory(@Reference ScopeRegistry registry,
+ @Reference WorkContext context,
+ @Monitor ScopeContainerMonitor monitor) {
+ registry.registerFactory(Scope.STATELESS, this);
+ this.context = context;
+ this.monitor = monitor;
+ }
+
+ public StatelessScopeContainer getInstance() throws ObjectCreationException {
+ return new StatelessScopeContainer(context, monitor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java
new file mode 100644
index 0000000000..7eef28f786
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java
@@ -0,0 +1,125 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * An interceptor to transform data accross databindings on the wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class DataBindingInteceptor implements Interceptor {
+ private Interceptor next;
+
+ private Operation<?> sourceOperation;
+
+ private Operation<?> targetOperation;
+
+ private Mediator mediator;
+
+ public DataBindingInteceptor(Wire sourceWire, Operation<?> sourceOperation, Operation<?> targetOperation) {
+ super();
+ // this.sourceWire = sourceWire;
+ this.sourceOperation = sourceOperation;
+ // this.targetWire = targetWire;
+ this.targetOperation = targetOperation;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.wire.Interceptor#getNext()
+ */
+ public Interceptor getNext() {
+ return next;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.wire.Interceptor#invoke(org.apache.tuscany.spi.wire.Message)
+ */
+ public Message invoke(Message msg) {
+ Object input = transform(msg.getBody(), sourceOperation.getInputType(), targetOperation.getInputType());
+ msg.setBody(input);
+ Message resultMsg = next.invoke(msg);
+ Object result = resultMsg.getBody();
+ // FIXME: How to deal with faults?
+ if (resultMsg.isFault()) {
+ // We need to figure out what fault type it is and then transform it back the source fault type
+ // throw new InvocationRuntimeException((Throwable) result);
+ return resultMsg;
+ } else {
+ if (sourceOperation.isNonBlocking()) {
+ // Not to reset the message body
+ return resultMsg;
+ }
+ // FIXME: Should we fix the Operation model so that getOutputType returns DataType<DataType<T>>?
+ DataType<DataType> targetType =
+ new DataType<DataType>("idl:output", Object.class, targetOperation.getOutputType());
+
+ targetType.setOperation(targetOperation.getOutputType().getOperation());
+ DataType<DataType> sourceType =
+ new DataType<DataType>("idl:output", Object.class, sourceOperation.getOutputType());
+ sourceType.setOperation(sourceOperation.getOutputType().getOperation());
+
+ Object newResult = transform(result, targetType, sourceType);
+ if (newResult != result) {
+ resultMsg.setBody(newResult);
+ }
+ }
+ return resultMsg;
+ }
+
+ private Object transform(Object source, DataType sourceType, DataType targetType) {
+ if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) {
+ return source;
+ }
+ Map<Class<?>, Object> metadata = new HashMap<Class<?>, Object>();
+ return mediator.mediate(source, sourceType, targetType, metadata);
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.wire.Interceptor#isOptimizable()
+ */
+ public boolean isOptimizable() {
+ return false;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.wire.Interceptor#setNext(org.apache.tuscany.spi.wire.Interceptor)
+ */
+ public void setNext(Interceptor next) {
+ this.next = next;
+ }
+
+ /**
+ * @param mediator the mediator to set
+ */
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java
new file mode 100644
index 0000000000..0da1ff90c1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java
@@ -0,0 +1,121 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorExtension;
+import org.apache.tuscany.spi.idl.java.JavaServiceContract;
+import org.apache.tuscany.spi.model.Operation;
+
+import org.apache.tuscany.api.annotation.DataContext;
+import org.apache.tuscany.api.annotation.DataType;
+
+/**
+ * The databinding annotation processor for java interfaces
+ *
+ * @version $Rev$ $Date$
+ */
+public class DataBindingJavaInterfaceProcessor extends JavaInterfaceProcessorExtension {
+
+ private static final String SIMPLE_JAVA_OBJECTS = "java.lang.Object";
+
+ private static final Class[] SIMPLE_JAVA_TYPES =
+ {Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Date.class,
+ Calendar.class, GregorianCalendar.class, Duration.class, XMLGregorianCalendar.class, BigInteger.class,
+ BigDecimal.class};
+
+ private static final Set<Class> SIMPLE_TYPE_SET = new HashSet<Class>(Arrays.asList(SIMPLE_JAVA_TYPES));
+
+ public void visitInterface(Class<?> clazz, Class<?> callbackClass, JavaServiceContract contract)
+ throws InvalidServiceContractException {
+ Map<String, Operation<Type>> operations = contract.getOperations();
+ processInterface(clazz, contract, operations);
+ if (callbackClass != null) {
+ Map<String, Operation<Type>> callbackOperations = contract.getCallbackOperations();
+ processInterface(callbackClass, contract, callbackOperations);
+ }
+ }
+
+ private void processInterface(Class<?> clazz,
+ JavaServiceContract contract,
+ Map<String, Operation<Type>> operations) {
+ DataType interfaceDataType = clazz.getAnnotation(DataType.class);
+ if (interfaceDataType != null) {
+ contract.setDataBinding(interfaceDataType.name());
+ // FIXME: [rfeng] Keep data context as metadata?
+ for (DataContext c : interfaceDataType.context()) {
+ contract.setMetaData(c.key(), c.value());
+ }
+ }
+ for (Method method : clazz.getMethods()) {
+ Operation<?> operation = operations.get(method.getName());
+ DataType operationDataType = method.getAnnotation(DataType.class);
+
+ if (operationDataType != null) {
+ operation.setDataBinding(operationDataType.name());
+ // FIXME: [rfeng] Keep data context as metadata?
+ for (DataContext c : operationDataType.context()) {
+ operation.setMetaData(c.key(), c.value());
+ }
+ }
+
+ String dataBinding = operation.getDataBinding();
+
+ // FIXME: We need a better way to identify simple java types
+ for (org.apache.tuscany.spi.model.DataType<?> d : operation.getInputType().getLogical()) {
+ adjustSimpleType(d, dataBinding);
+ }
+ if (operation.getOutputType() != null) {
+ adjustSimpleType(operation.getOutputType(), dataBinding);
+ }
+ for (org.apache.tuscany.spi.model.DataType<?> d : operation.getFaultTypes()) {
+ adjustSimpleType(d, dataBinding);
+ }
+ }
+ }
+
+ private void adjustSimpleType(org.apache.tuscany.spi.model.DataType<?> dataType, String dataBinding) {
+ Type type = dataType.getPhysical();
+ if (!(type instanceof Class)) {
+ return;
+ }
+ Class cls = (Class) dataType.getPhysical();
+ if (cls.isPrimitive() || SIMPLE_TYPE_SET.contains(cls)) {
+ dataType.setDataBinding(SIMPLE_JAVA_OBJECTS);
+ } else if (cls == String.class && (dataBinding == null || !dataBinding.equals(String.class.getName()))) {
+ // Identify the String as a simple type
+ dataType.setDataBinding(SIMPLE_JAVA_OBJECTS);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java
new file mode 100644
index 0000000000..3880d0ed12
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java
@@ -0,0 +1,90 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.core.databinding.javabeans.JavaBeansDataBinding;
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.model.DataType;
+
+/**
+ * The default implementation of a data binding registry
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class DataBindingRegistryImpl implements DataBindingRegistry {
+ private final Map<String, DataBinding> bindings = new HashMap<String, DataBinding>();
+
+ public DataBinding getDataBinding(String id) {
+ if (id == null) {
+ return null;
+ }
+ return bindings.get(id.toLowerCase());
+ }
+
+ public void register(DataBinding dataBinding) {
+ bindings.put(dataBinding.getName().toLowerCase(), dataBinding);
+ }
+
+ public DataBinding unregister(String id) {
+ if (id == null) {
+ return null;
+ }
+ return bindings.remove(id.toLowerCase());
+ }
+
+ public DataType introspectType(Class<?> javaType) {
+ DataType dataType = null;
+ for (DataBinding binding : bindings.values()) {
+ //don't introspect for JavaBeansDatabinding as all javatypes will anyways match to its basetype
+ //which is java.lang.Object. Default to this only if no databinding results
+ if (!binding.getName().equals(JavaBeansDataBinding.NAME)) {
+ dataType = binding.introspect(javaType);
+ }
+
+ if (dataType != null) {
+ return dataType;
+ }
+ }
+ return new DataType<Class>(JavaBeansDataBinding.NAME, Object.class, javaType);
+ }
+
+ public DataType introspectType(Object value) {
+ DataType dataType = null;
+ for (DataBinding binding : bindings.values()) {
+ //don't introspect for JavaBeansDatabinding as all javatypes will anyways match to its basetype
+ //which is java.lang.Object. Default to this only if no databinding results
+ if (!binding.getName().equals(JavaBeansDataBinding.NAME)) {
+ dataType = binding.introspect(value);
+ }
+ if (dataType != null) {
+ return dataType;
+ }
+ }
+ return new DataType<Class>(JavaBeansDataBinding.NAME, Object.class, value.getClass());
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java
new file mode 100644
index 0000000000..8bd1b810d4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java
@@ -0,0 +1,121 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WirePostProcessorExtension;
+
+/**
+ * This processor is responsible to add an interceptor to invocation chain if the source and target operations have
+ * different databinding requirements
+ *
+ * @version $Rev$ $Date$
+ */
+public class DataBindingWirePostProcessor extends WirePostProcessorExtension {
+ private Mediator mediator;
+
+ @Constructor({"mediator"})
+ public DataBindingWirePostProcessor(@Reference Mediator mediator) {
+ super();
+ this.mediator = mediator;
+ }
+
+ public void process(Wire wire) {
+ Map<Operation<?>, InvocationChain> chains = wire.getInvocationChains();
+ for (Map.Entry<Operation<?>, InvocationChain> entry : chains.entrySet()) {
+ Operation<?> sourceOperation = entry.getKey();
+ ServiceContract<?> serviceContract = wire.getTargetContract();
+ if (serviceContract == null) {
+ continue;
+ }
+ Collection<? extends Operation<?>> operations = serviceContract.getOperations().values();
+ Operation<?> targetOperation = getTargetOperation(operations, sourceOperation.getName());
+ String sourceDataBinding = sourceOperation.getDataBinding();
+ String targetDataBinding = targetOperation.getDataBinding();
+ if (sourceDataBinding == null && targetDataBinding == null) {
+ continue;
+ }
+ if (sourceDataBinding == null || targetDataBinding == null
+ || !sourceDataBinding.equals(targetDataBinding)) {
+ // Add the interceptor to the source side because multiple
+ // references can be wired
+ // to the same service
+ DataBindingInteceptor interceptor =
+ new DataBindingInteceptor(wire, sourceOperation, targetOperation);
+ interceptor.setMediator(mediator);
+ entry.getValue().addInterceptor(0, interceptor);
+ }
+ }
+
+ // Check if there's a callback
+ Map callbackOperations = wire.getSourceContract().getCallbackOperations();
+ if (callbackOperations == null || callbackOperations.isEmpty()) {
+ return;
+ }
+ //Object targetAddress = UriHelper.getBaseName(source.getUri());
+ Map<Operation<?>, InvocationChain> callbackChains = wire.getCallbackInvocationChains();
+ if (callbackChains == null) {
+ // callback chains could be null
+ return;
+ }
+ for (Map.Entry<Operation<?>, InvocationChain> entry : callbackChains.entrySet()) {
+ Operation<?> sourceOperation = entry.getKey();
+ Operation<?> targetOperation =
+ getTargetOperation(wire.getCallbackInvocationChains().keySet(), sourceOperation
+ .getName());
+ String sourceDataBinding = sourceOperation.getDataBinding();
+ String targetDataBinding = targetOperation.getDataBinding();
+ if (sourceDataBinding == null && targetDataBinding == null) {
+ continue;
+ }
+ if (sourceDataBinding == null || targetDataBinding == null
+ || !sourceDataBinding.equals(targetDataBinding)) {
+ // Add the interceptor to the source side because multiple
+ // references can be wired
+ // to the same service
+ DataBindingInteceptor interceptor =
+ new DataBindingInteceptor(wire, sourceOperation, targetOperation);
+ interceptor.setMediator(mediator);
+ entry.getValue().addInterceptor(0, interceptor);
+ }
+ }
+ }
+
+
+ private Operation getTargetOperation(Collection<? extends Operation<?>> operations, String operationName) {
+ for (Operation<?> op : operations) {
+ if (op.getName().equals(operationName)) {
+ return op;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java
new file mode 100644
index 0000000000..4f7d52b1cf
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java
@@ -0,0 +1,66 @@
+/*
+ * 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.core.databinding.impl;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidValueException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.ModelObject;
+
+/**
+ * The StAX loader for data type
+ */
+public class DataTypeLoader extends LoaderExtension<DataType> {
+ public static final QName DATA_BINDING =
+ new QName("http://tuscany.apache.org/xmlns/sca/databinding/1.0", "databinding");
+
+ @Constructor({"registry"})
+ public DataTypeLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public QName getXMLType() {
+ return DATA_BINDING;
+ }
+
+ public DataType load(
+ ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ assert DATA_BINDING.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ LoaderUtil.skipToEndElement(reader);
+ if (name == null) {
+ throw new InvalidValueException("The 'name' attrbiute is required");
+ }
+ DataType dataType = new DataType<Class>(name, Object.class, Object.class);
+ return dataType;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java
new file mode 100755
index 0000000000..02adf5860c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java
@@ -0,0 +1,357 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Directed, weighted graph
+ *
+ * @param <V> The type of vertex object
+ * @param <E> The type of edge object
+ */
+public class DirectedGraph<V, E> {
+ private final Map<V, Vertex> vertices = new HashMap<V, Vertex>();
+
+ /**
+ * Key for the shortest path cache
+ */
+ private final class VertexPair {
+ private Vertex source;
+
+ private Vertex target;
+
+ /**
+ * @param source
+ * @param target
+ */
+ private VertexPair(Vertex source, Vertex target) {
+ super();
+ this.source = source;
+ this.target = target;
+ }
+
+ public boolean equals(Object object) {
+ if (!VertexPair.class.isInstance(object)) {
+ return false;
+ }
+ VertexPair pair = (VertexPair)object;
+ return source == pair.source && target == pair.target;
+ }
+
+ public int hashCode() {
+ int x = source == null ? 0 : source.hashCode();
+ int y = target == null ? 0 : target.hashCode();
+ return x ^ y;
+ }
+
+ }
+
+ private final Map<VertexPair, Path> paths = new HashMap<VertexPair, Path>();
+
+ /**
+ * Vertex of a graph
+ */
+ public final class Vertex {
+ private V value;
+
+ // TODO: Do we want to support multiple edges for a vertex pair? If so,
+ // we should use a List instead of Map
+ private Map<Vertex, Edge> outEdges = new HashMap<Vertex, Edge>();
+
+ private Vertex(V value) {
+ this.value = value;
+ }
+
+ public String toString() {
+ return "(" + value + ")";
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public Map<Vertex, Edge> getOutEdges() {
+ return outEdges;
+ }
+
+ }
+
+ /**
+ * An Edge connects two vertices in one direction
+ */
+ public final class Edge {
+ private Vertex sourceVertex;
+
+ private Vertex targetVertex;
+
+ private E value;
+
+ private int weight;
+
+ public Edge(Vertex source, Vertex target, E value, int weight) {
+ this.sourceVertex = source;
+ this.targetVertex = target;
+ this.value = value;
+ this.weight = weight;
+ }
+
+ public String toString() {
+ return sourceVertex + "->" + targetVertex + "[" + value + "," + weight + "]";
+ }
+
+ public E getValue() {
+ return value;
+ }
+
+ public void setValue(E value) {
+ this.value = value;
+ }
+
+ public Vertex getTargetVertex() {
+ return targetVertex;
+ }
+
+ public void setTargetVertex(Vertex vertex) {
+ this.targetVertex = vertex;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public void setWeight(int weight) {
+ this.weight = weight;
+ }
+
+ public Vertex getSourceVertex() {
+ return sourceVertex;
+ }
+
+ public void setSourceVertex(Vertex sourceVertex) {
+ this.sourceVertex = sourceVertex;
+ }
+ }
+
+ private final class Node implements Comparable<Node> {
+
+ private long distance = Integer.MAX_VALUE;
+
+ private Node previous; // NOPMD by rfeng on 9/26/06 9:17 PM
+
+ private Vertex vertex; // NOPMD by rfeng on 9/26/06 9:17 PM
+
+ private Node(Vertex vertex) {
+ this.vertex = vertex;
+ }
+
+ public int compareTo(Node o) {
+ return (distance > o.distance) ? 1 : ((distance == o.distance) ? 0 : -1);
+ }
+ }
+
+ public void addEdge(V source, V target, E edgeValue, int weight) {
+ Vertex s = getVertex(source);
+ if (s == null) {
+ s = new Vertex(source);
+ vertices.put(source, s);
+ }
+ Vertex t = getVertex(target);
+ if (t == null) {
+ t = new Vertex(target);
+ vertices.put(target, t);
+ }
+ Edge edge = new Edge(s, t, edgeValue, weight);
+ s.outEdges.put(t, edge);
+ }
+
+ public Vertex getVertex(V source) {
+ Vertex s = vertices.get(source);
+ return s;
+ }
+
+ public boolean removeEdge(V source, V target) {
+ Vertex s = getVertex(source);
+ if (s == null) {
+ return false;
+ }
+
+ Vertex t = getVertex(target);
+ if (t == null) {
+ return false;
+ }
+
+ return s.outEdges.remove(t) != null;
+
+ }
+
+ public Edge getEdge(Vertex source, Vertex target) {
+ return source.outEdges.get(target);
+ }
+
+ public Edge getEdge(V source, V target) {
+ return getEdge(getVertex(source), getVertex(target));
+ }
+
+ /**
+ * Get the shortes path from the source vertex to the target vertex using
+ * Dijkstra's algorithm. If there's no path, null will be returned. If the
+ * source is the same as the target, it returns a path with empty edges with
+ * weight 0.
+ *
+ * @param sourceValue The value identifies the source
+ * @param targetValue The value identifies the target
+ * @return The shortest path
+ */
+ public Path getShortestPath(V sourceValue, V targetValue) {
+ Vertex source = getVertex(sourceValue);
+ if (source == null) {
+ return null;
+ }
+ Vertex target = getVertex(targetValue);
+ if (target == null) {
+ return null;
+ }
+
+ VertexPair pair = new VertexPair(source, target);
+ if (paths.containsKey(pair)) {
+ return paths.get(pair);
+ }
+
+ // HACK: To support same vertex
+ if (source == target) {
+ Path path = new Path();
+ Edge edge = getEdge(source, target);
+ if (edge != null) {
+ path.addEdge(edge);
+ }
+ paths.put(pair, path);
+ return path;
+ }
+
+ Map<Vertex, Node> nodes = new HashMap<Vertex, Node>();
+ for (Vertex v : vertices.values()) {
+ Node node = new Node(v);
+ if (v == source) {
+ node.distance = 0;
+ }
+ nodes.put(v, node);
+ }
+
+ Set<Node> otherNodes = new HashSet<Node>(nodes.values());
+ Set<Node> nodesOnPath = new HashSet<Node>();
+ while (!otherNodes.isEmpty()) {
+ Node nextNode = extractMin(otherNodes);
+ if (nextNode.vertex == target) {
+ Path path = getPath(nextNode);
+ paths.put(pair, path); // Cache it
+ return path;
+ }
+ nodesOnPath.add(nextNode);
+ for (Edge edge : nextNode.vertex.outEdges.values()) {
+ Node adjacentNode = nodes.get(edge.targetVertex);
+ if (nextNode.distance + edge.weight < adjacentNode.distance) {
+ adjacentNode.distance = nextNode.distance + edge.weight;
+ adjacentNode.previous = nextNode;
+ }
+ }
+ }
+ paths.put(pair, null); // Cache it
+ return null;
+ }
+
+ /**
+ * Searches for the vertex u in the vertex set Q that has the least d[u]
+ * value. That vertex is removed from the set Q and returned to the user.
+ *
+ * @param nodes
+ * @return
+ */
+ private Node extractMin(Set<Node> nodes) {
+ Node node = Collections.min(nodes);
+ nodes.remove(node);
+ return node;
+ }
+
+ /**
+ * The path between two vertices
+ */
+ public final class Path {
+ private List<Edge> edges = new LinkedList<Edge>();
+
+ private int weight;
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public List<Edge> getEdges() {
+ return edges;
+ }
+
+ public void addEdge(Edge edge) {
+ edges.add(0, edge);
+ weight += edge.weight;
+ }
+
+ public String toString() {
+ return edges + ", " + weight;
+ }
+ }
+
+ private Path getPath(Node t) {
+ if (t.distance == Integer.MAX_VALUE) {
+ return null;
+ }
+ Path path = new Path();
+ Node u = t;
+ while (u.previous != null) {
+ Edge edge = getEdge(u.previous.vertex, u.vertex);
+ path.addEdge(edge);
+ u = u.previous;
+ }
+ return path;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (Vertex v : vertices.values()) {
+ sb.append(v.outEdges.values()).append("\n");
+ }
+ return sb.toString();
+ }
+
+ public Map<V, Vertex> getVertices() {
+ return vertices;
+ }
+
+ public void addGraph(DirectedGraph<V, E> otherGraph) {
+ for (Vertex v : otherGraph.vertices.values()) {
+ for (Edge e : v.outEdges.values()) {
+ addEdge(e.sourceVertex.value, e.targetVertex.value, e.value, e.weight);
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java
new file mode 100644
index 0000000000..ba1de2132c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java
@@ -0,0 +1,215 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.List;
+import javax.xml.namespace.QName;
+
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.WrapperHandler;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.apache.tuscany.spi.model.ElementInfo;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.WrapperInfo;
+
+/**
+ * This is a special transformer to transform the input from one IDL to the other one
+ */
+@Service(Transformer.class)
+public class Input2InputTransformer extends TransformerExtension<Object[], Object[]> implements
+ PullTransformer<Object[], Object[]> {
+
+ private static final String IDL_INPUT = "idl:input";
+
+ protected DataBindingRegistry dataBindingRegistry;
+
+ protected Mediator mediator;
+
+ public Input2InputTransformer() {
+ super();
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return IDL_INPUT;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return IDL_INPUT;
+ }
+
+ /**
+ * @param mediator the mediator to set
+ */
+ @Reference
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Reference
+ public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) {
+ this.dataBindingRegistry = dataBindingRegistry;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType()
+ */
+ @Override
+ protected Class getSourceType() {
+ return Object[].class;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType()
+ */
+ @Override
+ protected Class getTargetType() {
+ return Object[].class;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.Transformer#getWeight()
+ */
+ public int getWeight() {
+ return 10000;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object[] transform(Object[] source, TransformationContext context) {
+ DataType<List<DataType<?>>> sourceType = context.getSourceDataType();
+ Operation<?> sourceOp = (Operation<?>) sourceType.getOperation();
+ boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle();
+
+ WrapperHandler sourceWrapperHandler = null;
+ if (sourceWrapped) {
+ sourceWrapperHandler = getWapperHandler(sourceType.getOperation().getDataBinding(), true);
+ }
+
+ DataType<List<DataType<QName>>> targetType = context.getTargetDataType();
+ Operation<?> targetOp = (Operation<?>) targetType.getOperation();
+ boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle();
+ WrapperHandler targetWrapperHandler = null;
+ if (targetWrapped) {
+ targetWrapperHandler = getWapperHandler(targetType.getOperation().getDataBinding(), true);
+ }
+
+ if ((!sourceWrapped) && targetWrapped) {
+ // Unwrapped --> Wrapped
+ WrapperInfo wrapper = targetOp.getWrapper();
+ ElementInfo wrapperElement = wrapper.getInputWrapperElement();
+
+ // If the source can be wrapped, wrapped it first
+ if (sourceWrapperHandler != null) {
+ Object sourceWrapper = sourceWrapperHandler.create(wrapperElement, context);
+ for (int i = 0; i < source.length; i++) {
+ ElementInfo argElement = wrapper.getInputChildElements().get(i);
+ sourceWrapperHandler.setChild(sourceWrapper, i, argElement, source[0]);
+ }
+ }
+ Object targetWrapper = targetWrapperHandler.create(wrapperElement, context);
+ if (source == null) {
+ return new Object[]{targetWrapper};
+ }
+ List<DataType<QName>> argTypes = wrapper.getUnwrappedInputType().getLogical();
+
+ for (int i = 0; i < source.length; i++) {
+ ElementInfo argElement = wrapper.getInputChildElements().get(i);
+ DataType<QName> argType = argTypes.get(i);
+ Object child = source[i];
+ child =
+ mediator.mediate(source[i], sourceType.getLogical().get(i), argType, context
+ .getMetadata());
+ targetWrapperHandler.setChild(targetWrapper, i, argElement, child);
+ }
+ return new Object[]{targetWrapper};
+ } else if (sourceWrapped && (!targetWrapped)) {
+ // Wrapped to Unwrapped
+ Object sourceWrapper = source[0];
+ List<ElementInfo> childElements = sourceOp.getWrapper().getInputChildElements();
+ Object[] target = new Object[childElements.size()];
+
+ targetWrapperHandler = getWapperHandler(targetType.getOperation().getDataBinding(), false);
+ if (targetWrapperHandler != null) {
+ ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement();
+ // Object targetWrapper =
+ // targetWrapperHandler.create(wrapperElement, context);
+ DataType<QName> targetWrapperType =
+ new DataType<QName>(targetType.getOperation().getDataBinding(), Object.class,
+ wrapperElement.getQName());
+ Object targetWrapper =
+ mediator.mediate(sourceWrapper,
+ sourceType.getLogical().get(0),
+ targetWrapperType,
+ context.getMetadata());
+ for (int i = 0; i < childElements.size(); i++) {
+ ElementInfo childElement = childElements.get(i);
+ target[i] = targetWrapperHandler.getChild(targetWrapper, i, childElement);
+ }
+ } else {
+ for (int i = 0; i < childElements.size(); i++) {
+ ElementInfo childElement = childElements.get(i);
+ Object child = sourceWrapperHandler.getChild(sourceWrapper, i, childElement);
+ DataType<QName> childType =
+ sourceOp.getWrapper().getUnwrappedInputType().getLogical().get(i);
+ target[i] =
+ mediator.mediate(child, childType, targetType.getLogical().get(i), context
+ .getMetadata());
+ }
+ }
+ return target;
+ } else {
+ // Assuming wrapper to wrapper conversion can be handled here as
+ // well
+ Object[] newArgs = new Object[source.length];
+ for (int i = 0; i < source.length; i++) {
+ Object child =
+ mediator.mediate(source[i], sourceType.getLogical().get(i), targetType.getLogical()
+ .get(i), context.getMetadata());
+ newArgs[i] = child;
+ }
+ return newArgs;
+ }
+ }
+
+ private WrapperHandler getWapperHandler(String dataBindingId, boolean required) {
+ DataBinding dataBinding = dataBindingRegistry.getDataBinding(dataBindingId);
+ WrapperHandler wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler();
+ if (wrapperHandler == null && required) {
+ throw new TransformationException(
+ "No wrapper handler is provided for databinding: " + dataBindingId);
+ }
+ return wrapperHandler;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java
new file mode 100644
index 0000000000..589a96ed71
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java
@@ -0,0 +1,168 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Scope;
+
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.databinding.DataPipe;
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.TransformerRegistry;
+import org.apache.tuscany.spi.model.DataType;
+
+/**
+ * Default Mediator implementation
+ */
+@Scope("COMPOSITE")
+public class MediatorImpl implements Mediator {
+
+ private DataBindingRegistry dataBindingRegistry;
+
+ private TransformerRegistry transformerRegistry;
+
+ @Reference
+ public void setTransformerRegistry(TransformerRegistry transformerRegistry) {
+ this.transformerRegistry = transformerRegistry;
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Reference
+ public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) {
+ this.dataBindingRegistry = dataBindingRegistry;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.Mediator#mediate(java.lang.Object,org.apache.tuscany.spi.model.DataType,
+ *org.apache.tuscany.spi.model.DataType,Map)
+ */
+ @SuppressWarnings("unchecked")
+ public Object mediate(Object source,
+ DataType sourceDataType,
+ DataType targetDataType,
+ Map<Class<?>, Object> metadata) {
+ if (sourceDataType == null) {
+ sourceDataType = dataBindingRegistry.introspectType(source);
+ }
+ if (sourceDataType == null) {
+ return source;
+ } else if (sourceDataType.equals(targetDataType)) {
+ return source;
+ }
+
+ List<Transformer> path = getTransformerChain(sourceDataType, targetDataType);
+
+ Object result = source;
+ int size = path.size();
+ int i = 0;
+ while (i < size) {
+ Transformer transformer = path.get(i);
+ TransformationContext context =
+ createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata);
+ // the source and target type
+ if (transformer instanceof PullTransformer) {
+ // For intermediate node, set data type to null
+ result = ((PullTransformer) transformer).transform(result, context);
+ } else if (transformer instanceof PushTransformer) {
+ DataPipe dataPipe = (i < size - 1) ? (DataPipe) path.get(++i) : null;
+ ((PushTransformer) transformer).transform(result, dataPipe.getSink(), context);
+ result = dataPipe.getResult();
+ }
+ i++;
+ }
+
+ return result;
+ }
+
+ private TransformationContext createTransformationContext(DataType sourceDataType,
+ DataType targetDataType,
+ int size,
+ int index,
+ Transformer transformer,
+ Map<Class<?>, Object> metadata) {
+ DataType sourceType =
+ (index == 0) ? sourceDataType : new DataType<Object>(transformer.getSourceDataBinding(),
+ Object.class, null);
+ DataType targetType =
+ (index == size - 1) ? targetDataType : new DataType<Object>(transformer.getTargetDataBinding(),
+ Object.class, null);
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ TransformationContext context =
+ new TransformationContextImpl(sourceType, targetType, classLoader, metadata);
+ return context;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void mediate(Object source,
+ Object target,
+ DataType sourceDataType,
+ DataType targetDataType,
+ Map<Class<?>, Object> metadata) {
+ if (source == null) {
+ // Shortcut for null value
+ return;
+ }
+ if (sourceDataType == null) {
+ sourceDataType = dataBindingRegistry.introspectType(source);
+ }
+ if (sourceDataType == null) {
+ return;
+ } else if (sourceDataType.equals(targetDataType)) {
+ return;
+ }
+
+ List<Transformer> path = getTransformerChain(sourceDataType, targetDataType);
+ Object result = source;
+ int size = path.size();
+ for (int i = 0; i < size; i++) {
+ Transformer transformer = path.get(i);
+ TransformationContext context =
+ createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata);
+
+ if (transformer instanceof PullTransformer) {
+ result = ((PullTransformer) transformer).transform(result, context);
+ } else if (transformer instanceof PushTransformer) {
+ DataPipe dataPipe = (i < size - 1) ? (DataPipe) path.get(++i) : null;
+ Object sink = dataPipe != null ? dataPipe.getSink() : target;
+ ((PushTransformer) transformer).transform(result, sink, context);
+ result = (dataPipe != null) ? dataPipe.getResult() : null;
+ }
+ }
+ }
+
+ private List<Transformer> getTransformerChain(DataType sourceDataType, DataType targetDataType) {
+ String sourceId = sourceDataType.getDataBinding();
+ String targetId = targetDataType.getDataBinding();
+ List<Transformer> path = transformerRegistry.getTransformerChain(sourceId, targetId);
+ if (path == null) {
+ throw new TransformationException("No path found for the transformation");
+ }
+ return path;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java
new file mode 100644
index 0000000000..c9c7b1239f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java
@@ -0,0 +1,200 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.List;
+import javax.xml.namespace.QName;
+
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.WrapperHandler;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.apache.tuscany.spi.model.ElementInfo;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.WrapperInfo;
+
+/**
+ * This is a special transformer to transform the output from one IDL to the other one
+ */
+@Service(Transformer.class)
+public class Output2OutputTransformer extends TransformerExtension<Object, Object> implements
+ PullTransformer<Object, Object> {
+ private static final String IDL_OUTPUT = "idl:output";
+
+ protected DataBindingRegistry dataBindingRegistry;
+
+ protected Mediator mediator;
+
+ /**
+ *
+ */
+ public Output2OutputTransformer() {
+ super();
+ }
+
+ /**
+ * @param mediator the mediator to set
+ */
+ @Reference
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Reference
+ public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) {
+ this.dataBindingRegistry = dataBindingRegistry;
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return IDL_OUTPUT;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return IDL_OUTPUT;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType()
+ */
+ @Override
+ protected Class getSourceType() {
+ return Object.class;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType()
+ */
+ @Override
+ protected Class getTargetType() {
+ return Object.class;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.Transformer#getWeight()
+ */
+ public int getWeight() {
+ return 10;
+ }
+
+ private WrapperHandler getWapperHandler(Operation<?> operation) {
+ String dataBindingId;
+ dataBindingId = operation.getDataBinding();
+ DataBinding dataBinding = dataBindingRegistry.getDataBinding(dataBindingId);
+ WrapperHandler wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler();
+ if (wrapperHandler == null) {
+ throw new TransformationException(
+ "No wrapper handler is provided for databinding: " + dataBindingId);
+ }
+ return wrapperHandler;
+ }
+
+ private WrapperHandler getWapperHandler(String dataBindingId) {
+ DataBinding dataBinding = dataBindingRegistry.getDataBinding(dataBindingId);
+ return dataBinding == null ? null : dataBinding.getWrapperHandler();
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object transform(Object response, TransformationContext context) {
+ try {
+ DataType<DataType> sourceType = context.getSourceDataType();
+ Operation<?> sourceOp = (Operation<?>) sourceType.getOperation();
+ boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle();
+ WrapperHandler sourceWrapperHandler = null;
+ if (sourceWrapped) {
+ sourceWrapperHandler = getWapperHandler(sourceOp);
+ }
+
+ DataType<DataType> targetType = context.getTargetDataType();
+ Operation<?> targetOp = (Operation<?>) targetType.getOperation();
+ boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle();
+ WrapperHandler targetWrapperHandler = null;
+ if (targetWrapped) {
+ targetWrapperHandler = getWapperHandler(targetOp);
+ }
+
+ if ((!sourceWrapped) && targetWrapped) {
+ // Unwrapped --> Wrapped
+ WrapperInfo wrapper = targetOp.getWrapper();
+ Object targetWrapper =
+ targetWrapperHandler.create(wrapper.getOutputWrapperElement(), context);
+
+ List<ElementInfo> childElements = wrapper.getOutputChildElements();
+ if (childElements.isEmpty()) {
+ // void output
+ return targetWrapper;
+ }
+ ElementInfo argElement = childElements.get(0);
+ DataType<QName> argType = wrapper.getUnwrappedOutputType();
+ Object child = response;
+ child = mediator.mediate(response, sourceType.getLogical(), argType, context.getMetadata());
+ targetWrapperHandler.setChild(targetWrapper, 0, argElement, child);
+ return targetWrapper;
+ } else if (sourceWrapped && (!targetWrapped)) {
+ // Wrapped to Unwrapped
+ Object sourceWrapper = response;
+ List<ElementInfo> childElements = sourceOp.getWrapper().getOutputChildElements();
+ if (childElements.isEmpty()) {
+ // The void output
+ return null;
+ }
+ ElementInfo childElement = childElements.get(0);
+
+ targetWrapperHandler = getWapperHandler(targetType.getLogical().getDataBinding());
+ if (targetWrapperHandler != null) {
+ ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement();
+ // Object targetWrapper =
+ // targetWrapperHandler.create(wrapperElement, context);
+ DataType<QName> targetWrapperType =
+ new DataType<QName>(targetType.getLogical().getDataBinding(), Object.class,
+ wrapperElement.getQName());
+ Object targetWrapper =
+ mediator.mediate(sourceWrapper, sourceType.getLogical(), targetWrapperType, context
+ .getMetadata());
+ return targetWrapperHandler.getChild(targetWrapper, 0, childElement);
+ } else {
+ Object child = sourceWrapperHandler.getChild(sourceWrapper, 0, childElement);
+ DataType<?> childType = sourceOp.getWrapper().getUnwrappedOutputType();
+ return mediator.mediate(child, childType, targetType.getLogical(), context.getMetadata());
+ }
+ } else {
+ // FIXME: Do we want to handle wrapped to wrapped?
+ return mediator.mediate(response, sourceType.getLogical(), targetType.getLogical(), context
+ .getMetadata());
+ }
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java
new file mode 100644
index 0000000000..1252885244
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java
@@ -0,0 +1,244 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.Message;
+
+import org.apache.tuscany.core.util.JavaIntrospectionHelper;
+
+/**
+ * An interceptor to enforce pass-by-value semantics for remotable interfaces
+ *
+ * @version $Rev$ $Date$
+ */
+public class PassByValueInterceptor implements Interceptor {
+ private DataBinding[] argsDataBindings;
+ private DataBinding resultDataBinding;
+
+ private DataBinding dataBinding;
+
+ private Interceptor next;
+
+ public Interceptor getNext() {
+ return next;
+ }
+
+ public boolean isOptimizable() {
+ return false;
+ }
+
+ public void setNext(Interceptor next) {
+ this.next = next;
+ }
+
+ public Message invoke(Message msg) {
+ Object obj = msg.getBody();
+ msg.setBody(copy((Object[]) obj));
+ Message result = getNext().invoke(msg);
+
+ if (!result.isFault()) {
+ result.setBody(copy(result.getBody(), getResultDataBinding()));
+ }
+ return result;
+ }
+
+
+ public Object[] copy(Object[] args) {
+ if (args == null) {
+ return null;
+ }
+ Object[] copiedArgs = new Object[args.length];
+ Map<Object, Object> map = new IdentityHashMap<Object, Object>();
+ for (int i = 0; i < args.length; i++) {
+ if (args[i] == null) {
+ copiedArgs[i] = null;
+ } else {
+ Object copiedArg = map.get(args[i]);
+ if (copiedArg != null) {
+ copiedArgs[i] = copiedArg;
+ } else {
+ DataBinding dataBinding =
+ (getArgsDataBindings() != null) ? getArgsDataBindings()[i] : null;
+ copiedArg = copy(args[i], dataBinding);
+ map.put(args[i], copiedArg);
+ copiedArgs[i] = copiedArg;
+ }
+ }
+ }
+ return copiedArgs;
+ }
+
+ public Object copy(Object arg, DataBinding argDataBinding) {
+ if (arg == null) {
+ return null;
+ }
+ Object copiedArg;
+ if (dataBinding != null) {
+ copiedArg = dataBinding.copy(arg);
+ } else {
+ if (argDataBinding != null) {
+ copiedArg = argDataBinding.copy(arg);
+ } else {
+ final Class clazz = arg.getClass();
+ if (JavaIntrospectionHelper.isImmutable(clazz)) {
+ // Immutable classes
+ return arg;
+ }
+ copiedArg = copyJavaObject(arg);
+ }
+ }
+ return copiedArg;
+ }
+
+ private Object copyJavaObject(Object arg) {
+ try {
+ return deserializeJavaObject(serializeJavaObject(arg));
+ } catch (IllegalArgumentException e) {
+ throw e;
+ //System.out.println("Problem serializing...");
+ //return arg;
+ }
+ }
+
+ public byte[] serializeJavaObject(Object arg) throws IllegalArgumentException {
+ if (arg == null) {
+ return null;
+ }
+
+ ByteArrayOutputStream bos = null;
+ ObjectOutputStream oos = null;
+
+ try {
+ if (arg instanceof Serializable) {
+ bos = new ByteArrayOutputStream();
+ oos = getObjectOutputStream(bos);
+ oos.writeObject(arg);
+
+ return bos.toByteArray();
+ } else {
+ throw new IllegalArgumentException("Unable to serialize using Java Serialization");
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Exception while serializing argument ", e);
+ } finally {
+ try {
+ if (oos != null) {
+ oos.close();
+ }
+ if (bos != null) {
+ bos.close();
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Exception while serializing argument ", e);
+ }
+ }
+ }
+
+ public Object deserializeJavaObject(byte[] arg) {
+ if (arg == null) {
+ return null;
+ }
+ final Class clazz = arg.getClass();
+ if (JavaIntrospectionHelper.isImmutable(clazz)) {
+ // Immutable classes
+ return arg;
+ }
+
+ ByteArrayInputStream bis = null;
+ ObjectInputStream ois = null;
+
+ try {
+ bis = new ByteArrayInputStream(arg);
+ ois = getObjectInputStream(bis, clazz.getClassLoader());
+
+ return ois.readObject();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Exception when attempting to Java Deserialization of object ", e);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Exception when attempting to Java Deserialization of object ", e);
+ } finally {
+ try {
+ if (ois != null) {
+ ois.close();
+ }
+ assert bis != null;
+ bis.close();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Exception when attempting to Java Deserialization of object ", e);
+ }
+ }
+ }
+
+ protected ObjectOutputStream getObjectOutputStream(OutputStream os) throws IOException {
+ return new ObjectOutputStream(os);
+ }
+
+ protected ObjectInputStream getObjectInputStream(InputStream is, final ClassLoader cl) throws IOException {
+ return new ObjectInputStream(is) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ try {
+ return Class.forName(desc.getName(), false, cl);
+ } catch (ClassNotFoundException e) {
+ return super.resolveClass(desc);
+ }
+ }
+
+ };
+ }
+
+ public DataBinding getDataBinding() {
+ return dataBinding;
+ }
+
+ public void setDataBinding(DataBinding dataBinding) {
+ this.dataBinding = dataBinding;
+ }
+
+ public DataBinding[] getArgsDataBindings() {
+ return argsDataBindings;
+ }
+
+ public void setArgsDataBindings(DataBinding[] argsDataBindings) {
+ this.argsDataBindings = argsDataBindings;
+ }
+
+ public DataBinding getResultDataBinding() {
+ return resultDataBinding;
+ }
+
+ public void setResultDataBinding(DataBinding retDataBinding) {
+ this.resultDataBinding = retDataBinding;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java
new file mode 100644
index 0000000000..ad4598f063
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java
@@ -0,0 +1,182 @@
+/*
+ * 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.core.databinding.impl;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WirePostProcessorExtension;
+
+/**
+ * This processor is responsible for enforcing the pass-by-value semantics required of Remotable interfaces. This is
+ * done by adding a pass-by-value interceptor to the inbound invocation chain of a target if the target interface is
+ * Remotable.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PassByValueWirePostProcessor extends WirePostProcessorExtension {
+ //private DataBindingRegistry dataBindingRegistry;
+
+ public PassByValueWirePostProcessor() {
+ super();
+
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Reference
+ public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) {
+ // this.dataBindingRegistry = dataBindingRegistry;
+ }
+
+ public void process(Wire wire) {
+
+ }
+
+// public void process(SCAObject source, OutboundWire sourceWire, SCAObject target, InboundWire targetWire) {
+// Interceptor tailInterceptor;
+// PassByValueInterceptor passByValueInterceptor;
+// Operation<?> targetOperation;
+// Operation<?> sourceOperation;
+// DataBinding[] argsDataBindings;
+// DataBinding resultDataBinding;
+//
+// boolean allowsPassByReference = false;
+// // JFM this needs to be fixed
+// if (target instanceof AtomicComponentExtension) {
+// allowsPassByReference =
+// ((AtomicComponentExtension) target).isAllowsPassByReference();
+// }
+// if (targetWire.getSourceContract().isRemotable()
+// && !allowsPassByReference) {
+// Map<Operation<?>, InboundInvocationChain> chains = targetWire.getInboundInvocationChains();
+// for (Map.Entry<Operation<?>, InboundInvocationChain> entry : chains.entrySet()) {
+// targetOperation = entry.getKey();
+// sourceOperation =
+// getSourceOperation(sourceWire.getOutboundInvocationChains().keySet(), targetOperation.getName());
+//
+//
+// if (null != sourceOperation) {
+// argsDataBindings = resolveArgsDataBindings(targetOperation);
+// resultDataBinding = resolveResultDataBinding(targetOperation);
+// passByValueInterceptor = new PassByValueInterceptor();
+// passByValueInterceptor.setDataBinding(getDataBinding(targetOperation));
+// passByValueInterceptor.setArgsDataBindings(argsDataBindings);
+// passByValueInterceptor.setResultDataBinding(resultDataBinding);
+// entry.getValue().addInterceptor(0, passByValueInterceptor);
+// tailInterceptor =
+// sourceWire.getOutboundInvocationChains().get(sourceOperation).getTailInterceptor();
+// if (tailInterceptor != null) {
+// tailInterceptor.setNext(passByValueInterceptor);
+// }
+// }
+// }
+// }
+//
+// // Check if there's a callback
+// Map callbackOperations = sourceWire.getSourceContract().getCallbackOperations();
+// allowsPassByReference = false;
+// if (source instanceof AtomicComponentExtension) {
+// allowsPassByReference =
+// ((AtomicComponentExtension) source).isAllowsPassByReference();
+// }
+//
+// if (sourceWire.getSourceContract().isRemotable()
+// && !allowsPassByReference
+// && callbackOperations != null
+// && !callbackOperations.isEmpty()) {
+// //URI targetAddress = UriHelper.getBaseName(source.getUri());
+// Map<Operation<?>, InboundInvocationChain> callbackChains = sourceWire.getTargetCallbackInvocationChains();
+// for (Map.Entry<Operation<?>, InboundInvocationChain> entry : callbackChains.entrySet()) {
+// targetOperation = entry.getKey();
+// sourceOperation =
+// getSourceOperation(targetWire.getSourceCallbackInvocationChains(
+// sourceWire.getSourceUri()).keySet(),
+// targetOperation.getName());
+//
+// argsDataBindings = resolveArgsDataBindings(targetOperation);
+// resultDataBinding = resolveResultDataBinding(targetOperation);
+//
+// passByValueInterceptor = new PassByValueInterceptor();
+// passByValueInterceptor.setDataBinding(getDataBinding(targetOperation));
+// passByValueInterceptor.setArgsDataBindings(argsDataBindings);
+// passByValueInterceptor.setResultDataBinding(resultDataBinding);
+//
+// entry.getValue().addInterceptor(0, passByValueInterceptor);
+// tailInterceptor =
+// targetWire.getSourceCallbackInvocationChains(sourceWire.getSourceUri()).get(sourceOperation)
+// .getTailInterceptor();
+// if (tailInterceptor != null) {
+// tailInterceptor.setNext(passByValueInterceptor);
+// }
+// }
+// }
+// }
+
+// private Operation getSourceOperation(Set<Operation<?>> operations, String operationName) {
+// for (Operation<?> op : operations) {
+// if (op.getName().equals(operationName)) {
+// return op;
+// }
+// }
+// return null;
+// }
+//
+// private DataBinding getDataBinding(Operation<?> operation) {
+// String dataBinding = operation.getDataBinding();
+// if (dataBinding == null) {
+// ServiceContract<?> serviceContract = operation.getServiceContract();
+// dataBinding = serviceContract.getDataBinding();
+// }
+// return dataBindingRegistry.getDataBinding(dataBinding);
+//
+// }
+
+// @SuppressWarnings("unchecked")
+// private DataBinding[] resolveArgsDataBindings(Operation operation) {
+// List<DataType<?>> argumentTypes = (List<DataType<?>>) operation.getInputType().getLogical();
+// DataBinding[] argDataBindings = new DataBinding[argumentTypes.size()];
+// int count = 0;
+// for (DataType argType : argumentTypes) {
+// argDataBindings[count] = null;
+// if (argType != null) {
+// if (argType.getLogical() instanceof Class) {
+// argDataBindings[count] =
+// dataBindingRegistry.getDataBinding(((Class) argType.getLogical()).getName());
+// }
+// }
+// ++count;
+// }
+// return argDataBindings;
+// }
+//
+// private DataBinding resolveResultDataBinding(Operation operation) {
+// DataType<?> resultType = (DataType<?>) operation.getOutputType();
+// DataBinding resultBinding = null;
+// if (resultType != null && resultType.getLogical() instanceof Class) {
+// Class<?> logical = (Class<?>) resultType.getLogical();
+// resultBinding = dataBindingRegistry.getDataBinding(logical.getName());
+// }
+// return resultBinding;
+// }
+//
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java
new file mode 100755
index 0000000000..388ea710a7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.core.databinding.impl;
+
+import org.apache.tuscany.spi.databinding.DataPipe;
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+
+/**
+ * A utility class to connect PushTransformer and DataPipe to create a
+ * PullTransformer
+ *
+ * @param <S> Source type
+ * @param <I> Intermidate type
+ * @param <R> Result type
+ */
+public class PipedTransformer<S, I, R> implements PullTransformer<S, R> {
+ private PushTransformer<S, I> pusher;
+
+ private DataPipe<I, R> pipe;
+
+ /**
+ * @param pumper
+ * @param pipe
+ */
+ public PipedTransformer(PushTransformer<S, I> pumper, DataPipe<I, R> pipe) {
+ super();
+ this.pusher = pumper;
+ this.pipe = pipe;
+ }
+
+ public R transform(S source, TransformationContext context) {
+ pusher.transform(source, pipe.getSink(), context);
+ return pipe.getResult();
+ }
+
+ public String getSourceDataBinding() {
+ return pusher.getSourceDataBinding();
+ }
+
+ public String getTargetDataBinding() {
+ return pipe.getTargetDataBinding();
+ }
+
+ public int getWeight() {
+ return pusher.getWeight() + pipe.getWeight();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java
new file mode 100644
index 0000000000..b1550c9f0a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.core.databinding.impl;
+
+import org.osoa.sca.annotations.Property;
+
+import org.apache.tuscany.spi.databinding.extension.DataBindingExtension;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+
+/**
+ * Simple databinding represented by a base java type. A SCDL property className is used to customize this component.
+ * <p/>
+ * The following illustrates how a simple data binding can be registered as a SCA component.
+ * <p/>
+ * <pre>
+ * &lt;component name="databinding.MyDataBinding"&gt;<br>
+ * &nbsp;&nbsp;&lt;system:implementation.java
+ * class="org.apache.tuscany.databinding.impl.SimpleDataBinding"/&gt;<br>
+ * &nbsp;&nbsp;&lt;property name="className"&gt;my.Type&lt;/property&gt;<br>
+ * &lt/component&gt;
+ * </pre>
+ *
+ * @version $Rv$ $Date$
+ */
+public class SimpleDataBinding extends DataBindingExtension {
+
+ public SimpleDataBinding(@Property(name = "className")String className) throws MissingResourceException {
+ super(resolve(className));
+ }
+
+ private static Class<?> resolve(String className) throws MissingResourceException {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ return Class.forName(className, false, classLoader);
+ } catch (ClassNotFoundException e) {
+ classLoader = SimpleDataBinding.class.getClassLoader();
+ try {
+ return Class.forName(className, false, classLoader);
+ } catch (ClassNotFoundException e1) {
+ throw new MissingResourceException(className, e1);
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java
new file mode 100755
index 0000000000..47f340097b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.model.DataType;
+
+public class TransformationContextImpl implements TransformationContext {
+ private DataType sourceDataType;
+
+ private DataType targetDataType;
+
+ private final Map<Class<?>, Object> metadata = new HashMap<Class<?>, Object>();
+
+ private WeakReference<ClassLoader> classLoaderRef;
+
+ public TransformationContextImpl() {
+ super();
+ setClassLoader(Thread.currentThread().getContextClassLoader());
+ }
+
+ public TransformationContextImpl(DataType sourceDataType,
+ DataType targetDataType,
+ ClassLoader classLoader,
+ Map<Class<?>, Object> metadata) {
+ super();
+ this.sourceDataType = sourceDataType;
+ this.targetDataType = targetDataType;
+ setClassLoader(classLoader);
+ if (metadata != null) {
+ this.metadata.putAll(metadata);
+ }
+ }
+
+ public DataType getSourceDataType() {
+ return sourceDataType;
+ }
+
+ public DataType getTargetDataType() {
+ return targetDataType;
+ }
+
+ public void setSourceDataType(DataType sourceDataType) {
+ this.sourceDataType = sourceDataType;
+ }
+
+ public void setTargetDataType(DataType targetDataType) {
+ this.targetDataType = targetDataType;
+ }
+
+ public final void setClassLoader(ClassLoader classLoader) {
+ this.classLoaderRef = new WeakReference<ClassLoader>(classLoader);
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoaderRef.get();
+ }
+
+ public Map<Class<?>, Object> getMetadata() {
+ return metadata;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java
new file mode 100755
index 0000000000..c8bfa1cc8c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.databinding.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.TransformerRegistry;
+
+/**
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class TransformerRegistryImpl implements TransformerRegistry {
+
+ private final DirectedGraph<Object, Transformer> graph = new DirectedGraph<Object, Transformer>();
+
+ public void registerTransformer(String sourceType, String resultType, int weight, Transformer transformer) {
+ graph.addEdge(sourceType, resultType, transformer, weight);
+ }
+
+ public void registerTransformer(Transformer transformer) {
+ graph.addEdge(transformer.getSourceDataBinding(),
+ transformer.getTargetDataBinding(),
+ transformer,
+ transformer.getWeight());
+ }
+
+ public boolean unregisterTransformer(String sourceType, String resultType) {
+ return graph.removeEdge(sourceType, resultType);
+ }
+
+ public Transformer getTransformer(String sourceType, String resultType) {
+ DirectedGraph<Object, Transformer>.Edge edge = graph.getEdge(sourceType, resultType);
+ return (edge == null) ? null : edge.getValue();
+ }
+
+ public List<Transformer> getTransformerChain(String sourceType, String resultType) {
+ List<Transformer> transformers = new ArrayList<Transformer>();
+ DirectedGraph<Object, Transformer>.Path path = graph.getShortestPath(sourceType, resultType);
+ if (path == null) {
+ return null;
+ }
+ for (DirectedGraph<Object, Transformer>.Edge edge : path.getEdges()) {
+ transformers.add(edge.getValue());
+ }
+ return transformers;
+ }
+
+ public String toString() {
+ return graph.toString();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java
new file mode 100644
index 0000000000..38f02cdc28
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Transformer to convert data from DOM Node to JavaBean
+ */
+@Service(Transformer.class)
+public class DOMNode2JavaBeanTransformer extends XML2JavaBeanTransformer<Node> {
+
+ @Override
+ public List<Node> getChildElements(Node parent) throws XML2JavaMapperException {
+ NodeList nodeList = parent.getChildNodes();
+ List<Node> nodeArrayList = new ArrayList<Node>(nodeList.getLength());
+ for (int count = 0; count < nodeList.getLength(); ++count) {
+ nodeArrayList.add(nodeList.item(count));
+ }
+
+ return nodeArrayList;
+ }
+
+ @Override
+ public String getElementName(Node element) throws XML2JavaMapperException {
+ return element.getNodeName();
+ }
+
+ @Override
+ public String getText(Node element) throws XML2JavaMapperException {
+ if (element instanceof Document) {
+ element = ((Document) element).getDocumentElement();
+ }
+ return element.getTextContent();
+ }
+
+ @Override
+ public boolean isTextElement(Node element) throws XML2JavaMapperException {
+ return element.getNodeType() == Node.TEXT_NODE;
+ }
+
+ public Class getSourceType() {
+ return Node.class;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java
new file mode 100644
index 0000000000..3f88a4ee89
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.api.TuscanyRuntimeException;
+
+/**
+ * This exception is used to encapsulate and rethrow exceptions that arise out
+ * of converting JavaBean objects to XML
+ */
+public class Java2XMLMapperException extends TuscanyRuntimeException {
+ private static final long serialVersionUID = 6811924384399578686L;
+
+ private QName xmlElementName;
+ private String javaFieldName;
+ private Class javaType;
+
+ public Java2XMLMapperException(String message) {
+ super(message);
+ }
+
+ public Java2XMLMapperException(Throwable cause) {
+ super(cause);
+ }
+
+ public String getJavaFieldName() {
+ return javaFieldName;
+ }
+
+ public void setJavaFieldName(String javaFieldName) {
+ this.javaFieldName = javaFieldName;
+ }
+
+ public Class getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(Class javaType) {
+ this.javaType = javaType;
+ }
+
+ public QName getXmlElementName() {
+ return xmlElementName;
+ }
+
+ public void setXmlElementName(QName xmlElementName) {
+ this.xmlElementName = xmlElementName;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java
new file mode 100644
index 0000000000..5925e87b69
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Transformer to convert data from a JavaBean object to DOM Node
+ */
+@Service(Transformer.class)
+public class JavaBean2DOMNodeTransformer extends JavaBean2XMLTransformer<Node> {
+
+ public static final String COLON = ":";
+ private Document factory;
+
+ public JavaBean2DOMNodeTransformer() {
+ super();
+ try {
+ factory = DOMHelper.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new Java2XMLMapperException(e);
+ }
+ }
+
+ @Override
+ public void appendChild(Node parentElement, Node childElement) throws Java2XMLMapperException {
+ parentElement.appendChild(childElement);
+ }
+
+ @Override
+ public Node createElement(QName qName) throws Java2XMLMapperException {
+ String qualifedName =
+ (qName.getPrefix() == null || qName.getPrefix().length() <= 0) ? qName.getLocalPart()
+ : qName.getPrefix() + COLON + qName.getLocalPart();
+ return factory.createElementNS(qName.getNamespaceURI(), qualifedName);
+ }
+
+ @Override
+ public Node createText(String textData) throws Java2XMLMapperException {
+ return factory.createTextNode(textData);
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java
new file mode 100644
index 0000000000..5d4b69ffbb
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java
@@ -0,0 +1,221 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Transformer to convert data from a JavaBean object to xml
+ */
+@Service(Transformer.class)
+public abstract class JavaBean2XMLTransformer<T> extends TransformerExtension<Object, T> implements
+ PullTransformer<Object, T> {
+
+ public static final String GET = "get";
+ public static final String PREFIX = "n";
+ public static final String PERIOD = ".";
+ public static final String FWD_SLASH = "/";
+ public static final String HTTP = "http://";
+ private static int prefixCount = 1;
+
+ protected SimpleTypeMapperExtension mapper;
+
+ public JavaBean2XMLTransformer() {
+ this.mapper = new SimpleTypeMapperExtension();
+ }
+
+ public T transform(Object source, TransformationContext context) {
+ QName rootElementName = (QName)context.getTargetDataType().getMetadata("RootElementName");
+ if (rootElementName == null) {
+ rootElementName = new QName(resolveRootElementName(source.getClass()));
+ }
+ T root = createElement(rootElementName);
+ appendChildElements(root,
+ resolveElementName(source.getClass()),
+ source.getClass(),
+ source,
+ context);
+ return root;
+ }
+
+ private void appendChildElements(T parent,
+ QName elementName,
+ Class javaType,
+ Object javaObject,
+ TransformationContext context) {
+ T element = null;
+ if (javaObject != null) {
+ if (javaType.isPrimitive() || isSimpleJavaType(javaObject)) {
+ appendChild(parent, createText(mapper.toXMLLiteral(null, javaObject, context)));
+ } else if (javaType.isArray()) {
+ boolean arrayDone = false;
+ Object arrayObject = null;
+ for (int count = 0; !arrayDone; ++count) {
+ try {
+ arrayObject = Array.get(javaObject, count);
+ element = createElement(elementName);
+ appendChild(parent, element);
+ appendChildElements(element,
+ elementName,
+ javaType.getComponentType(),
+ arrayObject,
+ context);
+ } catch (ArrayIndexOutOfBoundsException e1) {
+ arrayDone = true;
+ }
+ }
+ } else {
+ Field[] javaFields = javaType.getFields();
+ for (Field aField : javaFields) {
+ try {
+ QName fieldElementName = new QName(aField.getName());
+ if (!aField.getType().isArray()) {
+ element = createElement(fieldElementName);
+ appendChild(parent, element);
+ appendChildElements(element,
+ fieldElementName,
+ aField.getType(),
+ aField.get(javaObject),
+ context);
+ } else {
+ appendChildElements(parent,
+ fieldElementName,
+ aField.getType(),
+ aField.get(javaObject),
+ context);
+ }
+ } catch (IllegalAccessException e) {
+ Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e);
+ java2xmlEx.setJavaFieldName(aField.getName());
+ java2xmlEx.setJavaType(javaType);
+ throw java2xmlEx;
+ }
+ }
+
+ Method[] methods = javaType.getDeclaredMethods();
+ String fieldName = null;
+ for (Method aMethod : methods) {
+ try {
+ if (Modifier.isPublic(aMethod.getModifiers()) && aMethod.getName().startsWith(GET)
+ && aMethod.getParameterTypes().length == 0) {
+ fieldName = resolveFieldFromMethod(aMethod.getName());
+ try {
+ javaType.getField(fieldName);
+ } catch (NoSuchFieldException e) {
+ QName fieldElementName = new QName(fieldName);
+ if (aMethod.getReturnType().isArray()) {
+ appendChildElements(parent, fieldElementName, aMethod.getReturnType(), aMethod
+ .invoke(javaObject, new Object[0]), context);
+ } else {
+ element = createElement(fieldElementName);
+ appendChild(parent, element);
+ appendChildElements(element, fieldElementName, aMethod.getReturnType(), aMethod
+ .invoke(javaObject, new Object[0]), context);
+ }
+ }
+ }
+ } catch (IllegalAccessException e) {
+ Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e);
+ java2xmlEx.setJavaFieldName(fieldName);
+ java2xmlEx.setJavaType(javaType);
+ throw java2xmlEx;
+ } catch (InvocationTargetException e) {
+ Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e);
+ java2xmlEx.setJavaFieldName(fieldName);
+ java2xmlEx.setJavaType(javaType);
+ throw java2xmlEx;
+ }
+ }
+ }
+ }
+ }
+
+ public Class getSourceType() {
+ return Object.class;
+ }
+
+ private boolean isSimpleJavaType(Object javaObject) {
+ if (javaObject instanceof String) {
+ return true;
+ }
+ if (javaObject instanceof Byte || javaObject instanceof Character
+ || javaObject instanceof Short
+ || javaObject instanceof Integer
+ || javaObject instanceof Long
+ || javaObject instanceof Float
+ || javaObject instanceof Double) {
+ return true;
+ }
+ if (javaObject instanceof GregorianCalendar || javaObject instanceof Date
+ || javaObject instanceof XMLGregorianCalendar
+ || javaObject instanceof byte[]
+ || javaObject instanceof QName) {
+ return true;
+ }
+ return false;
+ }
+
+ private String resolveRootElementName(Class javaType) {
+ if (javaType.isArray()) {
+ return javaType.getComponentType().getSimpleName() + "_collection";
+ } else {
+ return javaType.getSimpleName() + "_instance";
+ }
+ }
+
+
+ private QName resolveElementName(Class javaType) {
+ if (javaType.isArray()) {
+ return new QName(javaType.getComponentType().getSimpleName());
+ } else {
+ return new QName(javaType.getSimpleName());
+ }
+ }
+
+ private String resolveFieldFromMethod(String methodName) {
+ StringBuffer fieldName = new StringBuffer();
+ fieldName.append(Character.toLowerCase(methodName.charAt(GET.length())));
+ fieldName.append(methodName.substring(GET.length() + 1));
+ return fieldName.toString();
+ }
+
+ public String getNexPrefix() {
+ return PREFIX + prefixCount++;
+ }
+
+ public abstract T createElement(QName qName) throws Java2XMLMapperException;
+ public abstract T createText(String textData) throws Java2XMLMapperException;
+ public abstract void appendChild(T parentElement, T childElement) throws Java2XMLMapperException;
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java
new file mode 100644
index 0000000000..a944706918
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.databinding.extension.DataBindingExtension;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * DataBinding for JavaBeans
+ */
+@Service(DataBinding.class)
+public class JavaBeansDataBinding extends DataBindingExtension {
+
+ public static final String NAME = Object.class.getName();
+
+ public JavaBeansDataBinding() {
+ super(Object.class);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java
new file mode 100644
index 0000000000..7f9753259c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java
@@ -0,0 +1,299 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.apache.tuscany.spi.model.ElementInfo;
+import org.apache.tuscany.spi.model.TypeInfo;
+
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Transformer to convert data from XML to JavaBean
+ */
+@Service(Transformer.class)
+public abstract class XML2JavaBeanTransformer<T> extends TransformerExtension<T, Object> implements
+ PullTransformer<T, Object> {
+
+ public static final String SET = "set";
+
+ protected SimpleTypeMapperExtension mapper;
+
+ public XML2JavaBeanTransformer() {
+ this.mapper = new SimpleTypeMapperExtension();
+ }
+
+ public Object transform(T source, TransformationContext context) {
+ TypeInfo xmlType =
+ (TypeInfo) context.getSourceDataType().getMetadata(TypeInfo.class.getName());
+ if (xmlType == null) {
+ ElementInfo element =
+ (ElementInfo) context.getSourceDataType()
+ .getMetadata(ElementInfo.class.getName());
+ xmlType = (TypeInfo) element.getType();
+ }
+
+ return toJavaObject(xmlType, source, context);
+ }
+
+ public Object toJavaObject(TypeInfo xmlType, T xmlElement, TransformationContext context) {
+ if (xmlType.isSimpleType()) {
+ return mapper.toJavaObject(xmlType, getText(xmlElement), context);
+ } else {
+ Class<?> javaType = (Class<?>) context.getTargetDataType().getLogical();
+ return createJavaObject(xmlElement, javaType, context);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <L> L createJavaObject(T element, Class<L> javaType, TransformationContext context)
+ throws XML2JavaMapperException {
+ List<T> childElements = getChildElements(element);
+ if (childElements.size() == 1 && isTextElement(childElements.get(0))) {
+ return (L) mapper.toJavaObject(mapper.getXMLType(javaType),
+ getText(childElements.get(0)),
+ context);
+ } else {
+ String fieldName = null;
+ try {
+ L javaInstance = javaType.newInstance();
+ Map<Field, List<Object>> arrayFields = new Hashtable<Field, List<Object>>();
+ Map<Method, List<Object>> arraySetters = new Hashtable<Method, List<Object>>();
+ for (int count = 0; count < childElements.size(); ++count) {
+ if (!isTextElement(childElements.get(count))) {
+ fieldName = getElementName(childElements.get(count));
+ try {
+ Field javaField = javaType.getField(fieldName);
+ setFieldValue(javaInstance,
+ javaField,
+ childElements.get(count),
+ arrayFields,
+ context);
+
+ } catch (NoSuchFieldException e1) {
+ setFieldValueUsingSetter(javaType,
+ javaInstance,
+ fieldName,
+ childElements.get(count),
+ arraySetters,
+ context);
+ }
+ }
+ }
+
+ setArrayValues(javaInstance, arrayFields, arraySetters);
+ return javaInstance;
+ } catch (Exception e2) {
+ XML2JavaMapperException xml2JavaEx = new XML2JavaMapperException(e2);
+ xml2JavaEx.setJavaType(javaType);
+ xml2JavaEx.setJavaFieldName(fieldName);
+ throw xml2JavaEx;
+ }
+ }
+ }
+
+ private void setFieldValue(Object javaInstance,
+ Field javaField,
+ T fieldValue,
+ Map<Field, List<Object>> arrayFields,
+ TransformationContext context) throws IllegalAccessException {
+ Class<?> javaFieldType = (Class<?>) javaField.getType();
+
+ if (javaFieldType.isArray()) {
+ Class<?> componentType = javaFieldType.getComponentType();
+ List<Object> fldValueArray = arrayFields.get(javaField);
+ if (fldValueArray == null) {
+ fldValueArray = new ArrayList<Object>();
+ arrayFields.put(javaField, fldValueArray);
+ }
+ fldValueArray.add(createJavaObject(fieldValue, componentType, context));
+ } else {
+ javaField.setAccessible(true);
+ javaField.set(javaInstance, createJavaObject(fieldValue, javaFieldType, context));
+ }
+ }
+
+ private void setFieldValueUsingSetter(Class javaType,
+ Object javaInstance,
+ String fieldName,
+ T fieldValue,
+ Map<Method, List<Object>> arraySetters,
+ TransformationContext context) throws IllegalAccessException,
+ InvocationTargetException {
+ char firstChar = Character.toUpperCase(fieldName.charAt(0));
+ StringBuilder methodName = new StringBuilder(SET + fieldName);
+ methodName.setCharAt(SET.length(), firstChar);
+ boolean methodNotFound = true;
+
+ for (int methodCount = 0; methodNotFound && methodCount < javaType.getMethods().length; ++methodCount) {
+ Method aMethod = javaType.getMethods()[methodCount];
+ if (aMethod.getName().equals(methodName.toString())
+ && aMethod.getParameterTypes().length == 1) {
+ Class<?> paramType = aMethod.getParameterTypes()[0];
+
+ if (paramType.isArray()) {
+ Class<?> componentType = paramType.getComponentType();
+ List<Object> setterValueArray = arraySetters.get(aMethod);
+ if (setterValueArray == null) {
+ setterValueArray = new ArrayList<Object>();
+ arraySetters.put(aMethod, setterValueArray);
+ }
+ setterValueArray.add(createJavaObject(fieldValue, componentType, context));
+ } else {
+ aMethod.invoke(javaInstance, new Object[] {createJavaObject(fieldValue,
+ paramType,
+ context)});
+ }
+ methodNotFound = false;
+ }
+ }
+
+ if (methodNotFound) {
+ XML2JavaMapperException xml2JavaEx =
+ new XML2JavaMapperException("No field or setter method to configure xml data");
+ xml2JavaEx.setJavaFieldName(fieldName);
+ xml2JavaEx.setJavaType(javaType);
+ throw xml2JavaEx;
+ }
+ }
+
+ private void setArrayValues(Object javaInstance,
+ Map<Field, List<Object>> arrayFields,
+ Map<Method, List<Object>> arraySetters) throws IllegalAccessException,
+ InvocationTargetException {
+ if (arrayFields.size() > 0) {
+ for (Field javaField : arrayFields.keySet()) {
+ javaField.setAccessible(true);
+
+ if (javaField.getType().getComponentType().isPrimitive()) {
+ javaField.set(javaInstance, createPrimitiveArray(javaField.getType()
+ .getComponentType(),
+ arrayFields.get(javaField)));
+ } else {
+ javaField.set(javaInstance,
+ createNonPrimitiveArray(javaField.getType().getComponentType(),
+ arrayFields.get(javaField)));
+ }
+ }
+ }
+
+ if (arraySetters.size() > 0) {
+ for (Method aMethod : arraySetters.keySet()) {
+ Class paramType = aMethod.getParameterTypes()[0];
+ if (paramType.getComponentType().isPrimitive()) {
+ aMethod.invoke(javaInstance,
+ new Object[] {createPrimitiveArray(paramType.getComponentType(),
+ arraySetters.get(aMethod))});
+ } else {
+ aMethod.invoke(javaInstance,
+ new Object[] {createNonPrimitiveArray(paramType.getComponentType(),
+ arraySetters.get(aMethod))});
+ }
+ }
+ }
+ }
+
+ private Object createNonPrimitiveArray(Class fieldType, List values) {
+ Object objectArray = Array.newInstance(fieldType, values.size());
+ for (int count = 0; count < values.size(); ++count) {
+ Array.set(objectArray, count, values.get(count));
+ }
+ return objectArray;
+ }
+
+ private Object createPrimitiveArray(Class fieldType, List values) {
+ if (fieldType.isPrimitive()) {
+ if (fieldType.getName().equals("int")) {
+ int[] primitiveValues = new int[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Integer) values.get(count)).intValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("float")) {
+ float[] primitiveValues = new float[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Float) values.get(count)).floatValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("boolean")) {
+ boolean[] primitiveValues = new boolean[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Boolean) values.get(count)).booleanValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("char")) {
+ char[] primitiveValues = new char[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Character) values.get(count)).charValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("byte")) {
+ byte[] primitiveValues = new byte[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Byte) values.get(count)).byteValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("short")) {
+ short[] primitiveValues = new short[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Short) values.get(count)).shortValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("long")) {
+ long[] primitiveValues = new long[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Long) values.get(count)).longValue();
+ }
+ return primitiveValues;
+ } else if (fieldType.getName().equals("double")) {
+ double[] primitiveValues = new double[values.size()];
+ for (int count = 0; count < values.size(); ++count) {
+ primitiveValues[count] = ((Double) values.get(count)).doubleValue();
+ }
+ return primitiveValues;
+ }
+ }
+ return values;
+ }
+
+ public abstract String getText(T source) throws XML2JavaMapperException;
+
+ public abstract List<T> getChildElements(T parent) throws XML2JavaMapperException;
+
+ public abstract String getElementName(T element) throws XML2JavaMapperException;
+
+ public abstract boolean isTextElement(T element) throws XML2JavaMapperException;
+
+ public Class getTargetType() {
+ return Object.class;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java
new file mode 100644
index 0000000000..f2910e6946
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.databinding.javabeans;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.api.TuscanyRuntimeException;
+
+/**
+ * This exception is used to encapsulate and rethrow exceptions that arise out of converting XML Data to Java Objects.
+ *
+ * @version $Rev$ $Date$
+ */
+public class XML2JavaMapperException extends TuscanyRuntimeException {
+ private static final long serialVersionUID = 6596530102591630642L;
+
+ private QName xmlElementName;
+ private String javaFieldName;
+ private Class javaType;
+
+ public XML2JavaMapperException(String message) {
+ super(message);
+ }
+
+ public XML2JavaMapperException(Throwable cause) {
+ super(cause);
+ }
+
+ public QName getXmlElementName() {
+ return xmlElementName;
+ }
+
+ public void setXmlElementName(QName xmlElementName) {
+ this.xmlElementName = xmlElementName;
+ }
+
+ public String getJavaFieldName() {
+ return javaFieldName;
+ }
+
+ public void setJavaFieldName(String javaFieldName) {
+ this.javaFieldName = javaFieldName;
+ }
+
+ public Class getJavaType() {
+ return javaType;
+ }
+
+ public void setJavaType(Class javaType) {
+ this.javaType = javaType;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java
new file mode 100644
index 0000000000..d2df8cf888
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java
@@ -0,0 +1,56 @@
+/*
+ * 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.core.databinding.xml;
+
+
+import org.w3c.dom.Node;
+
+import org.apache.tuscany.spi.databinding.WrapperHandler;
+import org.apache.tuscany.spi.databinding.extension.DataBindingExtension;
+
+/**
+ * DOM DataBinding
+ *
+ * @version $Rev$ $Date$
+ */
+public class DOMDataBinding extends DataBindingExtension {
+ public static final String NAME = Node.class.getName();
+
+ public DOMDataBinding() {
+ super(Node.class);
+ }
+
+ @Override
+ public WrapperHandler getWrapperHandler() {
+ return new DOMWrapperHandler();
+ }
+
+ public Object copy(Object source) {
+ if (Node.class.isAssignableFrom(source.getClass())) {
+ Node nodeSource = (Node) source;
+ Node2String strTransformer = new Node2String();
+ String stringCopy = strTransformer.transform(nodeSource, null);
+
+ String2Node nodeTransformer = new String2Node();
+ return nodeTransformer.transform(stringCopy, null);
+ }
+
+ return super.copy(source);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java
new file mode 100644
index 0000000000..4ef0af6701
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java
@@ -0,0 +1,80 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.WrapperHandler;
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.apache.tuscany.spi.model.ElementInfo;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class DOMWrapperHandler implements WrapperHandler<Node> {
+
+ private Document document;
+
+ public DOMWrapperHandler() {
+ super();
+ try {
+ this.document = DOMHelper.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Node create(ElementInfo element, TransformationContext context) {
+ QName name = element.getQName();
+ return DOMHelper.createElement(document, name);
+ }
+
+ public Object getChild(Node wrapper, int i, ElementInfo element) {
+ int index = 0;
+ NodeList nodes = wrapper.getChildNodes();
+ for (int j = 0; j < nodes.getLength(); j++) {
+ Node node = nodes.item(j);
+ if (node.getNodeType() != Node.ELEMENT_NODE) {
+ continue;
+ }
+ if (index != i) {
+ index++;
+ } else {
+ QName name = DOMHelper.getQName(node);
+ if (name.equals(element.getQName())) {
+ return node;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void setChild(Node wrapper, int i, ElementInfo childElement, Object value) {
+ Node node = (Node) value;
+ if (node.getNodeType() == Node.DOCUMENT_NODE) {
+ node = ((Document) node).getDocumentElement();
+ }
+ wrapper.appendChild(wrapper.getOwnerDocument().importNode(node, true));
+ }
+} \ No newline at end of file
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java
new file mode 100644
index 0000000000..f94ddd545f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java
@@ -0,0 +1,1415 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import org.apache.tuscany.core.databinding.xml.StAXHelper.XMLFragmentStreamReader;
+
+public class DOMXMLStreamReader implements XMLFragmentStreamReader {
+ protected static class DelegatingNamespaceContext implements NamespaceContext {
+ private int counter;
+
+ private NamespaceContext parent;
+
+ private Map<String, String> prefixToNamespaceMapping = new HashMap<String, String>();
+
+ public DelegatingNamespaceContext(NamespaceContext parent) {
+ super();
+ this.parent = parent;
+
+ prefixToNamespaceMapping.put("xml", "http://www.w3.org/XML/1998/namespace");
+ prefixToNamespaceMapping.put("xmlns", "http://www.w3.org/2000/xmlns/");
+ prefixToNamespaceMapping.put("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ }
+
+ public synchronized QName createQName(String nsURI, String name) {
+ String prefix = nsURI != null ? (String) getPrefix(nsURI) : null;
+ if (prefix == null && nsURI != null && !nsURI.equals("")) {
+ prefix = "p" + (counter++);
+ }
+ if (prefix == null) {
+ prefix = "";
+ }
+ if (nsURI != null) {
+ prefixToNamespaceMapping.put(prefix, nsURI);
+ }
+ return new QName(nsURI, name, prefix);
+ }
+
+ public String getNamespaceURI(String prefix) {
+ if (prefix == null) {
+ throw new IllegalArgumentException("Prefix is null");
+ }
+
+ String ns = (String) prefixToNamespaceMapping.get(prefix);
+ if (ns != null) {
+ return ns;
+ } else if (parent != null) {
+ return parent.getNamespaceURI(prefix);
+ } else {
+ return null;
+ }
+ }
+
+ public String getPrefix(String nsURI) {
+ if (nsURI == null) {
+ throw new IllegalArgumentException("Namespace is null");
+ }
+ for (Map.Entry<String, String> entry1 : prefixToNamespaceMapping.entrySet()) {
+ Map.Entry entry = entry1;
+ if (entry.getValue().equals(nsURI)) {
+ return (String) entry.getKey();
+ }
+ }
+ if (parent != null) {
+ return parent.getPrefix(nsURI);
+ } else {
+ return null;
+ }
+ }
+
+ public Iterator getPrefixes(String nsURI) {
+ List<String> prefixList = new ArrayList<String>();
+ for (Map.Entry<String, String> entry : prefixToNamespaceMapping.entrySet()) {
+ if (entry.getValue().equals(nsURI)) {
+ prefixList.add(entry.getKey());
+ }
+ }
+ if (parent != null) {
+ for (Iterator i = parent.getPrefixes(nsURI); i.hasNext();) {
+ prefixList.add((String) i.next());
+ }
+ }
+ return prefixList.iterator();
+ }
+
+ public void registerMapping(String prefix, String nsURI) {
+ prefixToNamespaceMapping.put(prefix, nsURI);
+ }
+
+ public void removeMapping(String prefix) {
+ prefixToNamespaceMapping.remove(prefix);
+ }
+
+ public void setParent(NamespaceContext parent) {
+ this.parent = parent;
+ }
+ }
+
+ protected static class NameValuePair implements Map.Entry {
+ private Object key;
+
+ private Object value;
+
+ public NameValuePair(Object key, Object value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public Object getKey() {
+ return key;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public Object setValue(Object value) {
+ Object v = this.value;
+ this.value = value;
+ return v;
+ }
+
+ }
+
+ protected static class SimpleElementStreamReader implements XMLFragmentStreamReader {
+
+ private static final int END_ELEMENT_STATE = 2;
+
+ private static final int START_ELEMENT_STATE = 0;
+
+ private static final int START_ELEMENT_STATE_WITH_NULL = 3;
+
+ private static final int TEXT_STATE = 1;
+
+ private static final QName XSI_NIL_QNAME =
+ new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi");
+
+ private QName name;
+
+ private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(null);
+
+ private int state = START_ELEMENT_STATE;
+
+ private String value;
+
+ public SimpleElementStreamReader(QName name, String value) {
+ this.name = name;
+ this.value = value;
+ if (value == null) {
+ state = START_ELEMENT_STATE_WITH_NULL;
+ }
+ }
+
+ public void close() throws XMLStreamException {
+ // Do nothing - we've nothing to free here
+ }
+
+ public int getAttributeCount() {
+ if (state == START_ELEMENT_STATE_WITH_NULL) {
+ return 1;
+ }
+ if (state == START_ELEMENT_STATE) {
+ return 0;
+ } else {
+ throw new IllegalStateException();
+ }
+
+ }
+
+ public String getAttributeLocalName(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) {
+ return XSI_NIL_QNAME.getLocalPart();
+ }
+ if (state == START_ELEMENT_STATE) {
+ return null;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public QName getAttributeName(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) {
+ return XSI_NIL_QNAME;
+ }
+ if (state == START_ELEMENT_STATE) {
+ return null;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeNamespace(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) {
+ return XSI_NIL_QNAME.getNamespaceURI();
+ }
+ if (state == START_ELEMENT_STATE) {
+ return null;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributePrefix(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) {
+ return XSI_NIL_QNAME.getPrefix();
+ }
+ if (state == START_ELEMENT_STATE) {
+ return null;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeType(int i) {
+ return null; // not implemented
+ }
+
+ public String getAttributeValue(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) {
+ return "true";
+ }
+ if (state == START_ELEMENT_STATE) {
+ return null;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeValue(String string, String string1) {
+ if (state == TEXT_STATE) {
+ // todo something
+ return null;
+ } else {
+ return null;
+ }
+
+ }
+
+ public String getCharacterEncodingScheme() {
+ return null;
+ }
+
+ public String getElementText() throws XMLStreamException {
+ if (state == START_ELEMENT) {
+ // move to the end state and return the value
+ state = END_ELEMENT_STATE;
+ return value;
+ } else {
+ throw new XMLStreamException();
+ }
+
+ }
+
+ public String getEncoding() {
+ return "UTF-8";
+ }
+
+ public int getEventType() {
+ switch (state) {
+ case START_ELEMENT_STATE:
+ case START_ELEMENT_STATE_WITH_NULL:
+ return START_ELEMENT;
+ case END_ELEMENT_STATE:
+ return END_ELEMENT;
+ case TEXT_STATE:
+ return CHARACTERS;
+ default:
+ throw new UnsupportedOperationException();
+ // we've no idea what this is!!!!!
+ }
+
+ }
+
+ public String getLocalName() {
+ if (state != TEXT_STATE) {
+ return name.getLocalPart();
+ } else {
+ return null;
+ }
+ }
+
+ public Location getLocation() {
+ return new Location() {
+ public int getCharacterOffset() {
+ return 0;
+ }
+
+ public int getColumnNumber() {
+ return 0;
+ }
+
+ public int getLineNumber() {
+ return 0;
+ }
+
+ public String getPublicId() {
+ return null;
+ }
+
+ public String getSystemId() {
+ return null;
+ }
+ };
+ }
+
+ public QName getName() {
+ if (state != TEXT_STATE) {
+ return name;
+ } else {
+ return null;
+ }
+ }
+
+ public NamespaceContext getNamespaceContext() {
+ return this.namespaceContext;
+ }
+
+ public int getNamespaceCount() {
+ if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent()) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+ }
+
+ public String getNamespacePrefix(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) {
+ return XSI_NIL_QNAME.getPrefix();
+ } else {
+ return null;
+ }
+ }
+
+ public String getNamespaceURI() {
+ if (state != TEXT_STATE) {
+ return name.getNamespaceURI();
+ } else {
+ return null;
+ }
+
+ }
+
+ public String getNamespaceURI(int i) {
+ if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) {
+ return XSI_NIL_QNAME.getNamespaceURI();
+ } else {
+ return null;
+ }
+ }
+
+ public String getNamespaceURI(String prefix) {
+ return namespaceContext.getNamespaceURI(prefix);
+ }
+
+ public String getPIData() {
+ return null;
+ }
+
+ public String getPITarget() {
+ return null;
+ }
+
+ public String getPrefix() {
+ if (state != TEXT_STATE) {
+ return name.getPrefix();
+ } else {
+ return null;
+ }
+ }
+
+ public Object getProperty(String key) throws IllegalArgumentException {
+ return null;
+ }
+
+ public String getText() {
+ if (state == TEXT_STATE) {
+ return value;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public char[] getTextCharacters() {
+ if (state == TEXT_STATE) {
+ return value.toCharArray();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException {
+ // not implemented
+ throw new UnsupportedOperationException();
+ }
+
+ public int getTextLength() {
+ if (state == TEXT_STATE) {
+ return value.length();
+ } else {
+ throw new IllegalStateException();
+ }
+
+ }
+
+ public int getTextStart() {
+ if (state == TEXT_STATE) {
+ return 0;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getVersion() {
+ return null; // todo 1.0 ?
+ }
+
+ public boolean hasName() {
+ return state != TEXT_STATE;
+
+ }
+
+ public boolean hasNext() throws XMLStreamException {
+ return state != END_ELEMENT_STATE;
+ }
+
+ public boolean hasText() {
+ return state == TEXT_STATE;
+ }
+
+ public void init() {
+ // just add the current elements namespace and prefix to the this
+ // elements nscontext
+ registerNamespace(name.getPrefix(), name.getNamespaceURI());
+
+ }
+
+ public boolean isAttributeSpecified(int i) {
+ return false; // no attribs here
+ }
+
+ public boolean isCharacters() {
+ return state == TEXT_STATE;
+ }
+
+ public boolean isEndElement() {
+ return state == END_ELEMENT_STATE;
+ }
+
+ public boolean isEndOfFragment() {
+ return state == END_ELEMENT_STATE;
+ }
+
+ public boolean isStandalone() {
+ return false;
+ }
+
+ public boolean isStartElement() {
+ return state == START_ELEMENT_STATE || state == START_ELEMENT_STATE_WITH_NULL;
+ }
+
+ public boolean isWhiteSpace() {
+ return false; // no whitespaces here
+ }
+
+ /**
+ * Test whether the xsi namespace is present
+ *
+ * @return
+ */
+ private boolean isXsiNamespacePresent() {
+ return namespaceContext.getNamespaceURI(XSI_NIL_QNAME.getPrefix()) != null;
+ }
+
+ public int next() throws XMLStreamException {
+ switch (state) {
+ case START_ELEMENT_STATE:
+ state = TEXT_STATE;
+ return CHARACTERS;
+ case START_ELEMENT_STATE_WITH_NULL:
+ state = END_ELEMENT_STATE;
+ return END_ELEMENT;
+ case END_ELEMENT_STATE:
+ // oops, not supposed to happen!
+ throw new XMLStreamException("end already reached!");
+ case TEXT_STATE:
+ state = END_ELEMENT_STATE;
+ return END_ELEMENT;
+ default:
+ throw new XMLStreamException("unknown event type!");
+ }
+ }
+
+ public int nextTag() throws XMLStreamException {
+ return 0; // todo
+ }
+
+ /**
+ * @param prefix
+ * @param uri
+ */
+ private void registerNamespace(String prefix, String uri) {
+ // todo - need to fix this up to cater for cases where
+ // namespaces are having no prefixes
+ if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) {
+ // this namespace is not there. Need to declare it
+ namespaceContext.registerMapping(prefix, uri);
+ }
+ }
+
+ public void require(int i, String string, String string1) throws XMLStreamException {
+ // not implemented
+ }
+
+ public void setParentNamespaceContext(NamespaceContext nsContext) {
+ this.namespaceContext.setParent(nsContext);
+ }
+
+ public boolean standaloneSet() {
+ return false;
+ }
+
+ }
+
+ private static final int DELEGATED_STATE = 2;
+
+ private static final int END_ELEMENT_STATE = 1;
+
+ // states for this pullparser - it can only have three states
+ private static final int START_ELEMENT_STATE = 0;
+
+ private static final int TEXT_STATE = 3;
+
+ private Map.Entry[] attributes;
+
+ // reference to the child reader
+ private XMLFragmentStreamReader childReader;
+
+ // current property index
+ private int currentPropertyIndex;
+
+ private Map<String, String> declaredNamespaceMap = new HashMap<String, String>();
+
+ private QName elementQName;
+
+ // we always create a new namespace context
+ private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(null);
+
+ private Map.Entry[] properties;
+
+ private Element rootElement;
+
+ private String rootElementName;
+
+ private String rootElementURI;
+
+ // integer field that keeps the state of this
+ // parser.
+ private int state = START_ELEMENT_STATE;
+
+ public DOMXMLStreamReader(Node node) {
+ switch (node.getNodeType()) {
+ case Node.DOCUMENT_NODE:
+ this.rootElement = ((Document) node).getDocumentElement();
+ break;
+ case Node.ELEMENT_NODE:
+ this.rootElement = (Element) node;
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal Node");
+ }
+ this.rootElementName = rootElement.getLocalName();
+ this.rootElementURI = rootElement.getNamespaceURI();
+
+ declaredNamespaceMap.put("xml", "http://www.w3.org/XML/1998/namespace");
+ declaredNamespaceMap.put("xmlns", "http://www.w3.org/2000/xmlns/");
+ declaredNamespaceMap.put("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+
+ populateProperties();
+ }
+
+ /*
+ * we need to pass in a namespace context since when delegated, we've no
+ * idea of the current namespace context. So it needs to be passed on here!
+ */
+ protected DOMXMLStreamReader(QName elementQName, Map.Entry[] properties, Map.Entry[] attributes) {
+ // validate the lengths, since both the arrays are supposed
+ // to have
+ this.properties = properties;
+ this.elementQName = elementQName;
+ this.attributes = attributes;
+
+ }
+
+ public void close() throws XMLStreamException {
+ // do nothing here - we have no resources to free
+ }
+
+ public int getAttributeCount() {
+ return (state == DELEGATED_STATE) ? childReader.getAttributeCount()
+ : ((attributes != null) && (state == START_ELEMENT_STATE) ? attributes.length : 0);
+ }
+
+ public String getAttributeLocalName(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getAttributeLocalName(i);
+ } else if (state == START_ELEMENT_STATE) {
+ QName name = getAttributeName(i);
+ if (name == null) {
+ return null;
+ } else {
+ return name.getLocalPart();
+ }
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * @param i
+ * @return
+ */
+ public QName getAttributeName(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getAttributeName(i);
+ } else if (state == START_ELEMENT_STATE) {
+ if (attributes == null) {
+ return null;
+ } else {
+ if ((i >= (attributes.length)) || i < 0) { // out of range
+ return null;
+ } else {
+ // get the attribute pointer
+ Object attribPointer = attributes[i].getKey();
+ // case one - attrib name is null
+ // this should be the pointer to the OMAttribute then
+ if (attribPointer instanceof String) {
+ return new QName((String) attribPointer);
+ } else if (attribPointer instanceof QName) {
+ return (QName) attribPointer;
+ } else {
+ return null;
+ }
+ }
+ }
+ } else {
+ throw new IllegalStateException(); // as per the api contract
+ }
+
+ }
+
+ public String getAttributeNamespace(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getAttributeNamespace(i);
+ } else if (state == START_ELEMENT_STATE) {
+ QName name = getAttributeName(i);
+ if (name == null) {
+ return null;
+ } else {
+ return name.getNamespaceURI();
+ }
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributePrefix(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getAttributePrefix(i);
+ } else if (state == START_ELEMENT_STATE) {
+ QName name = getAttributeName(i);
+ if (name == null) {
+ return null;
+ } else {
+ return name.getPrefix();
+ }
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeType(int i) {
+ return null; // not supported
+ }
+
+ public String getAttributeValue(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getAttributeValue(i);
+ } else if (state == START_ELEMENT_STATE) {
+ if (attributes == null) {
+ return null;
+ } else {
+ if ((i >= (attributes.length)) || i < 0) { // out of range
+ return null;
+ } else {
+ // get the attribute pointer
+ Object attribPointer = attributes[i].getKey();
+ Object omAttribObj = attributes[i].getValue();
+ // case one - attrib name is null
+ // this should be the pointer to the OMAttribute then
+ if (attribPointer instanceof String) {
+ return (String) omAttribObj;
+ } else if (attribPointer instanceof QName) {
+ return (String) omAttribObj;
+ } else {
+ return null;
+ }
+ }
+ }
+ } else {
+ throw new IllegalStateException();
+ }
+
+ }
+
+ public String getAttributeValue(String nsUri, String localName) {
+
+ int attribCount = getAttributeCount();
+ String returnValue = null;
+ QName attribQualifiedName;
+ for (int i = 0; i < attribCount; i++) {
+ attribQualifiedName = getAttributeName(i);
+ if (nsUri == null) {
+ if (localName.equals(attribQualifiedName.getLocalPart())) {
+ returnValue = getAttributeValue(i);
+ break;
+ }
+ } else {
+ if (localName.equals(attribQualifiedName.getLocalPart()) && nsUri.equals(attribQualifiedName
+ .getNamespaceURI())) {
+ returnValue = getAttributeValue(i);
+ break;
+ }
+ }
+
+ }
+
+ return returnValue;
+ }
+
+ public String getCharacterEncodingScheme() {
+ return null; // todo - should we return something for this ?
+ }
+
+ /**
+ * todo implement the right contract for this
+ *
+ * @return
+ * @throws XMLStreamException
+ */
+ public String getElementText() throws XMLStreamException {
+ if (state == DELEGATED_STATE) {
+ return childReader.getElementText();
+ } else {
+ return null;
+ }
+
+ }
+
+ public String getEncoding() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getEncoding();
+ } else {
+ // we've no idea what the encoding is going to be in this case
+ // perhaps we ought to return some constant here, which the user
+ // might
+ // have access to change!
+ return null;
+ }
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ // / attribute handling
+ // /////////////////////////////////////////////////////////////////////////
+
+ public int getEventType() {
+ if (state == START_ELEMENT_STATE) {
+ return START_ELEMENT;
+ } else if (state == END_ELEMENT_STATE) {
+ return END_ELEMENT;
+ } else { // this is the delegated state
+ return childReader.getEventType();
+ }
+
+ }
+
+ public String getLocalName() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getLocalName();
+ } else if (state != TEXT_STATE) {
+ return elementQName.getLocalPart();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * @return
+ */
+ public Location getLocation() {
+ // return a default location
+ return new Location() {
+ public int getCharacterOffset() {
+ return 0;
+ }
+
+ public int getColumnNumber() {
+ return 0;
+ }
+
+ public int getLineNumber() {
+ return 0;
+ }
+
+ public String getPublicId() {
+ return null;
+ }
+
+ public String getSystemId() {
+ return null;
+ }
+ };
+ }
+
+ public QName getName() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getName();
+ } else if (state != TEXT_STATE) {
+ return elementQName;
+ } else {
+ throw new IllegalStateException();
+ }
+
+ }
+
+ public NamespaceContext getNamespaceContext() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getNamespaceContext();
+ } else {
+ return namespaceContext;
+ }
+
+ }
+
+ public int getNamespaceCount() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getNamespaceCount();
+ } else {
+ return declaredNamespaceMap.size();
+ }
+ }
+
+ /**
+ * @param i
+ * @return
+ */
+ public String getNamespacePrefix(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getNamespacePrefix(i);
+ } else if (state != TEXT_STATE) {
+ // order the prefixes
+ String[] prefixes = makePrefixArray();
+ if ((i >= prefixes.length) || (i < 0)) {
+ return null;
+ } else {
+ return prefixes[i];
+ }
+
+ } else {
+ throw new IllegalStateException();
+ }
+
+ }
+
+ public String getNamespaceURI() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getNamespaceURI();
+ } else if (state == TEXT_STATE) {
+ return null;
+ } else {
+ return elementQName.getNamespaceURI();
+ }
+ }
+
+ public String getNamespaceURI(int i) {
+ if (state == DELEGATED_STATE) {
+ return childReader.getNamespaceURI(i);
+ } else if (state != TEXT_STATE) {
+ String namespacePrefix = getNamespacePrefix(i);
+ return namespacePrefix == null ? null : (String) declaredNamespaceMap.get(namespacePrefix);
+ } else {
+ throw new IllegalStateException();
+ }
+
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ // //////////// end of attribute handling
+ // /////////////////////////////////////////////////////////////////////////
+
+ // //////////////////////////////////////////////////////////////////////////
+ // //////////// namespace handling
+ // //////////////////////////////////////////////////////////////////////////
+
+ public String getNamespaceURI(String prefix) {
+ return namespaceContext.getNamespaceURI(prefix);
+ }
+
+ public String getPIData() {
+ throw new UnsupportedOperationException("Yet to be implemented !!");
+ }
+
+ public String getPITarget() {
+ throw new UnsupportedOperationException("Yet to be implemented !!");
+ }
+
+ public String getPrefix() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getPrefix();
+ } else if (state == TEXT_STATE) {
+ return null;
+ } else {
+ return elementQName.getPrefix();
+ }
+ }
+
+ /**
+ * @param key
+ * @return
+ * @throws IllegalArgumentException
+ */
+ public Object getProperty(String key) throws IllegalArgumentException {
+ if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) {
+ return null;
+ } else if (state == TEXT_STATE) {
+ return null;
+ } else if (state == DELEGATED_STATE) {
+ return childReader.getProperty(key);
+ } else {
+ return null;
+ }
+
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ // /////// end of namespace handling
+ // /////////////////////////////////////////////////////////////////////////
+
+ public String getText() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getText();
+ } else if (state == TEXT_STATE) {
+ return (String) properties[currentPropertyIndex - 1].getValue();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public char[] getTextCharacters() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getTextCharacters();
+ } else if (state == TEXT_STATE) {
+ return properties[currentPropertyIndex - 1].getValue() == null ? new char[0]
+ : ((String) properties[currentPropertyIndex - 1].getValue()).toCharArray();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException {
+ if (state == DELEGATED_STATE) {
+ return childReader.getTextCharacters(i, chars, i1, i2);
+ } else if (state == TEXT_STATE) {
+ // todo - implement this
+ return 0;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextLength() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getTextLength();
+ } else if (state == TEXT_STATE) {
+ return 0; // assume text always starts at 0
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextStart() {
+ if (state == DELEGATED_STATE) {
+ return childReader.getTextStart();
+ } else if (state == TEXT_STATE) {
+ return 0; // assume text always starts at 0
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getVersion() {
+ return null;
+ }
+
+ public boolean hasName() {
+ // since this parser always has a name, the hasname
+ // has to return true if we are still navigating this element
+ // if not we should ask the child reader for it.
+ if (state == DELEGATED_STATE) {
+ return childReader.hasName();
+ } else {
+ return state != TEXT_STATE;
+ }
+ }
+
+ /**
+ * @return
+ * @throws XMLStreamException
+ */
+ public boolean hasNext() throws XMLStreamException {
+ if (state == DELEGATED_STATE) {
+ if (childReader.isEndOfFragment()) {
+ // the child reader is done. We shouldn't be getting the
+ // hasnext result from the child pullparser then
+ return true;
+ } else {
+ return childReader.hasNext();
+ }
+ } else {
+ return state == START_ELEMENT_STATE || state == TEXT_STATE;
+
+ }
+ }
+
+ /**
+ * check the validity of this implementation
+ *
+ * @return
+ */
+ public boolean hasText() {
+ if (state == DELEGATED_STATE) {
+ return childReader.hasText();
+ } else {
+ return state == TEXT_STATE;
+ }
+ }
+
+ /**
+ * we need to split out the calling to the populate namespaces seperately since this needs to be done *after*
+ * setting the parent namespace context. We cannot assume it will happen at construction!
+ */
+ public void init() {
+ // here we have an extra issue to attend to. we need to look at the
+ // prefixes and uris (the combination) and populate a hashmap of
+ // namespaces. The hashmap of namespaces will be used to serve the
+ // namespace context
+
+ populateNamespaceContext();
+ }
+
+ public boolean isAttributeSpecified(int i) {
+ return false; // not supported
+ }
+
+ public boolean isCharacters() {
+ if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) {
+ return false;
+ }
+ return childReader.isCharacters();
+ }
+
+ public boolean isEndElement() {
+ if (state == START_ELEMENT_STATE) {
+ return false;
+ } else if (state == END_ELEMENT_STATE) {
+ return true;
+ }
+ return childReader.isEndElement();
+ }
+
+ /**
+ * are we done ?
+ *
+ * @return
+ */
+ public boolean isEndOfFragment() {
+ return state == END_ELEMENT_STATE;
+ }
+
+ public boolean isStandalone() {
+ return true;
+ }
+
+ public boolean isStartElement() {
+ if (state == START_ELEMENT_STATE) {
+ return true;
+ } else if (state == END_ELEMENT_STATE) {
+ return false;
+ }
+ return childReader.isStartElement();
+ }
+
+ public boolean isWhiteSpace() {
+ if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) {
+ return false;
+ }
+ return childReader.isWhiteSpace();
+ }
+
+ /**
+ * Get the prefix list from the hastable and take that into an array
+ *
+ * @return
+ */
+ private String[] makePrefixArray() {
+ String[] prefixes =
+ (String[]) declaredNamespaceMap.keySet().toArray(new String[declaredNamespaceMap.size()]);
+ Arrays.sort(prefixes);
+ return prefixes;
+ }
+
+ public int next() throws XMLStreamException {
+ return updateStatus();
+ }
+
+ /**
+ * todo implement this
+ *
+ * @return
+ * @throws XMLStreamException
+ */
+ public int nextTag() throws XMLStreamException {
+ return 0;
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ // / Other utility methods
+ // ////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Populates a namespace context
+ */
+ private void populateNamespaceContext() {
+
+ // first add the current element namespace to the namespace context
+ // declare it if not found
+ registerNamespace(elementQName.getPrefix(), elementQName.getNamespaceURI());
+
+ // traverse through the attributes and populate the namespace context
+ // the attrib list can be of many combinations
+ // the valid combinations are
+ // String - String
+ // QName - QName
+ // null - OMAttribute
+
+ if (attributes != null) {
+ for (int i = 0; i < attributes.length; i++) { // jump in two
+ Object attribName = attributes[i].getKey();
+ if (attribName instanceof String) {
+ // ignore this case - Nothing to do
+ } else if (attribName instanceof QName) {
+ QName attribQName = (QName) attribName;
+ registerNamespace(attribQName.getPrefix(), attribQName.getNamespaceURI());
+
+ }
+ }
+ }
+
+ }
+
+ public final void populateProperties() {
+ if (properties != null) {
+ return;
+ }
+ if (elementQName == null) {
+ elementQName = namespaceContext.createQName(this.rootElementURI, this.rootElementName);
+ } else {
+ elementQName =
+ namespaceContext.createQName(elementQName.getNamespaceURI(), elementQName.getLocalPart());
+ }
+
+ List<Object> elementList = new ArrayList<Object>();
+ List<Object> attributeList = new ArrayList<Object>();
+ NamedNodeMap nodeMap = rootElement.getAttributes();
+ for (int i = 0; i < nodeMap.getLength(); i++) {
+ Attr attr = (Attr) nodeMap.item(i);
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.getNamespaceURI())) {
+ // Skip xmlns:xxx
+ if (!attr.getName().equals(attr.getLocalName())) {
+ // Skip xmlns="..."
+ registerNamespace(attr.getLocalName(), attr.getValue());
+ } else {
+ registerNamespace(XMLConstants.DEFAULT_NS_PREFIX, attr.getValue());
+ }
+ continue;
+ }
+ QName attrName = new QName(attr.getNamespaceURI(), attr.getLocalName());
+ NameValuePair pair = new NameValuePair(attrName, attr.getValue());
+ attributeList.add(pair);
+ }
+ NodeList nodeList = rootElement.getChildNodes();
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ Node node = nodeList.item(i);
+ switch (node.getNodeType()) {
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ NameValuePair pair = new NameValuePair(ELEMENT_TEXT, ((CharacterData) node).getData());
+ elementList.add(pair);
+ break;
+
+ case Node.ELEMENT_NODE:
+ Element element = (Element) node;
+ QName elementName = new QName(element.getNamespaceURI(), element.getLocalName());
+ pair = new NameValuePair(elementName, new DOMXMLStreamReader(element));
+ elementList.add(pair);
+ break;
+ }
+ }
+ properties = elementList.toArray(new Map.Entry[elementList.size()]);
+ attributes = attributeList.toArray(new Map.Entry[attributeList.size()]);
+ }
+
+ /**
+ * A convenient method to reuse the properties
+ *
+ * @return event to be thrown
+ * @throws XMLStreamException
+ */
+ private int processProperties() throws XMLStreamException {
+ // move to the next property depending on the current property
+ // index
+ Object propPointer = properties[currentPropertyIndex].getKey();
+ QName propertyQName = null;
+ boolean textFound = false;
+ if (propPointer == null) {
+ throw new XMLStreamException("property key cannot be null!");
+ } else if (propPointer instanceof String) {
+ // propPointer being a String has a special case
+ // that is it can be a the special constant ELEMENT_TEXT that
+ // says this text event
+ if (ELEMENT_TEXT.equals(propPointer)) {
+ textFound = true;
+ } else {
+ propertyQName = new QName((String) propPointer);
+ }
+ } else if (propPointer instanceof QName) {
+ propertyQName = (QName) propPointer;
+ } else {
+ // oops - we've no idea what kind of key this is
+ throw new XMLStreamException("unidentified property key!!!" + propPointer);
+ }
+
+ // ok! we got the key. Now look at the value
+ Object propertyValue = properties[currentPropertyIndex].getValue();
+ // cater for the special case now
+ if (textFound) {
+ // no delegation here - make the parser null and immediately
+ // return with the event characters
+ childReader = null;
+ state = TEXT_STATE;
+ currentPropertyIndex++;
+ return CHARACTERS;
+ } else if (propertyValue == null || propertyValue instanceof String) {
+ // strings are handled by the NameValuePairStreamReader
+ childReader = new SimpleElementStreamReader(propertyQName, (String) propertyValue);
+ childReader.setParentNamespaceContext(this.namespaceContext);
+ childReader.init();
+ } else if (propertyValue instanceof DOMXMLStreamReader) {
+ // ADBbean has it's own method to get a reader
+ XMLFragmentStreamReader reader = (DOMXMLStreamReader) propertyValue;
+ // we know for sure that this is an ADB XMLStreamreader.
+ // However we need to make sure that it is compatible
+ childReader = reader;
+ childReader.setParentNamespaceContext(this.namespaceContext);
+ childReader.init();
+ } else {
+ // all special possiblilities has been tried! Let's treat
+ // the thing as a bean and try generating events from it
+ throw new UnsupportedOperationException("Not supported");
+ // childReader = new
+ // WrappingXMLStreamReader(BeanUtil.getPullParser(propertyValue,
+ // propertyQName));
+ // we cannot register the namespace context here
+ }
+
+ // set the state here
+ state = DELEGATED_STATE;
+ // we are done with the delegation
+ // increment the property index
+ currentPropertyIndex++;
+ return childReader.getEventType();
+ }
+
+ /**
+ * @param prefix
+ * @param uri
+ */
+ private void registerNamespace(String prefix, String uri) {
+ if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) {
+ namespaceContext.registerMapping(prefix, uri);
+ declaredNamespaceMap.put(prefix, uri);
+ }
+ }
+
+ public void require(int i, String string, String string1) throws XMLStreamException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * add the namespace context
+ */
+
+ public void setParentNamespaceContext(NamespaceContext nsContext) {
+ // register the namespace context passed in to this
+ this.namespaceContext.setParent(nsContext);
+
+ }
+
+ public boolean standaloneSet() {
+ return true;
+ }
+
+ /**
+ * By far this should be the most important method in this class this method changes the state of the parser
+ * according to the change in the
+ */
+ private int updateStatus() throws XMLStreamException {
+ int returnEvent = -1; // invalid state is the default state
+ switch (state) {
+ case START_ELEMENT_STATE:
+ // current element is start element. We should be looking at the
+ // property list and making a pullparser for the property value
+ if (properties == null || properties.length == 0) {
+ // no properties - move to the end element state
+ // straightaway
+ state = END_ELEMENT_STATE;
+ returnEvent = END_ELEMENT;
+ } else {
+ // there are properties. now we should delegate this task to
+ // a
+ // child reader depending on the property type
+ returnEvent = processProperties();
+
+ }
+ break;
+ case END_ELEMENT_STATE:
+ // we've reached the end element already. If the user tries to
+ // push
+ // further ahead then it is an exception
+ throw new XMLStreamException("Trying to go beyond the end of the pullparser");
+
+ case DELEGATED_STATE:
+ if (childReader.isEndOfFragment()) {
+ // we've reached the end!
+ if (currentPropertyIndex > (properties.length - 1)) {
+ state = END_ELEMENT_STATE;
+ returnEvent = END_ELEMENT;
+ } else {
+ returnEvent = processProperties();
+ }
+ } else {
+ returnEvent = childReader.next();
+ }
+ break;
+
+ case TEXT_STATE:
+ // if there are any more event we should be delegating to
+ // processProperties. if not we just return an end element
+ if (currentPropertyIndex > (properties.length - 1)) {
+ state = END_ELEMENT_STATE;
+ returnEvent = END_ELEMENT;
+ } else {
+ returnEvent = processProperties();
+ }
+ break;
+ }
+ return returnEvent;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java
new file mode 100644
index 0000000000..e9757fa13c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.databinding.xml;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+
+/**
+ * Push DOM InputSource to Node
+ */
+@Service(Transformer.class)
+public class InputSource2Node extends TransformerExtension<InputSource, Node> implements
+ PullTransformer<InputSource, Node> {
+ private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer();
+
+ public Node transform(InputSource source, TransformationContext context) {
+ try {
+ Source streamSource = new StreamSource(source.getCharacterStream());
+ DOMResult result = new DOMResult();
+ TRANSFORMER.transform(streamSource, result, context);
+ return result.getNode();
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return InputSource.class;
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java
new file mode 100644
index 0000000000..be78a07ede
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core.databinding.xml;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Push InputSource to SAX
+ */
+@Service(Transformer.class)
+public class InputSource2SAX extends TransformerExtension<InputSource, ContentHandler> implements
+ PushTransformer<InputSource, ContentHandler> {
+
+ public void transform(InputSource source, ContentHandler target, TransformationContext context) {
+ try {
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setFeature("http://xml.org/sax/features/namespaces", true);
+ reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
+ reader.setContentHandler(target);
+ reader.parse(source);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return InputSource.class;
+ }
+
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java
new file mode 100644
index 0000000000..e103c82b33
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java
@@ -0,0 +1,67 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.InputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXSource;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+
+/**
+ * Push DOM InputSource to Node
+ */
+@Service(Transformer.class)
+public class InputStream2Node extends TransformerExtension<InputStream, Node> implements
+ PullTransformer<InputStream, Node> {
+ private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer();
+
+ public Node transform(InputStream source, TransformationContext context) {
+ try {
+ Source streamSource = new SAXSource(new InputSource(source));
+ DOMResult result = new DOMResult();
+ TRANSFORMER.transform(streamSource, result, context);
+ return result.getNode();
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return InputStream.class;
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java
new file mode 100644
index 0000000000..d74863ea95
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java
@@ -0,0 +1,62 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.InputStream;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Push InputStream to SAX
+ */
+@Service(Transformer.class)
+public class InputStream2SAX extends TransformerExtension<InputStream, ContentHandler> implements
+ PushTransformer<InputStream, ContentHandler> {
+ public void transform(InputStream source, ContentHandler target, TransformationContext context) {
+ try {
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setContentHandler(target);
+ reader.parse(new InputSource(source));
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return InputStream.class;
+ }
+
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java
new file mode 100644
index 0000000000..34fbdf8c6f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java
@@ -0,0 +1,66 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.OutputStream;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+/**
+ * Push DOM Node to OutputStream
+ */
+@Service(Transformer.class)
+public class Node2OutputStream extends TransformerExtension<Node, OutputStream> implements
+ PushTransformer<Node, OutputStream> {
+ private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer();
+
+ public void transform(Node source, OutputStream writer, TransformationContext context) {
+ try {
+ Source domSource = new DOMSource(source);
+ Result result = new StreamResult(writer);
+ TRANSFORMER.transform(domSource, result, context);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Node.class;
+ }
+
+ public Class getTargetType() {
+ return OutputStream.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java
new file mode 100755
index 0000000000..92378e96a3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java
@@ -0,0 +1,59 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.StringWriter;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+/**
+ * Transform DOM Node to XML String
+ */
+@Service(org.apache.tuscany.spi.databinding.Transformer.class)
+public class Node2String extends TransformerExtension<Node, String> implements PullTransformer<Node, String> {
+ private static final Node2Writer TRANSFORMER = new Node2Writer();
+
+ public String transform(Node source, TransformationContext context) {
+ try {
+ StringWriter writer = new StringWriter();
+ TRANSFORMER.transform(source, writer, context);
+ return writer.toString();
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Node.class;
+ }
+
+ public Class getTargetType() {
+ return String.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java
new file mode 100644
index 0000000000..96328fdd2f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.databinding.xml;
+
+import java.io.Writer;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+/**
+ * Push DOM Node to Writer
+ */
+@Service(Transformer.class)
+public class Node2Writer extends TransformerExtension<Node, Writer> implements PushTransformer<Node, Writer> {
+ private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer();
+
+ public void transform(Node source, Writer writer, TransformationContext context) {
+ try {
+ Source domSource = new DOMSource(source);
+ Result result = new StreamResult(writer);
+ TRANSFORMER.transform(domSource, result, context);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Node.class;
+ }
+
+ public Class getTargetType() {
+ return Writer.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java
new file mode 100644
index 0000000000..bff9051e01
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.core.databinding.xml.StAXHelper.XMLDocumentStreamReader;
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+/**
+ * Transform DOM Node to XML XMLStreamReader
+ */
+@Service(Transformer.class)
+public class Node2XMLStreamReader extends TransformerExtension<Node, XMLStreamReader> implements
+ PullTransformer<Node, XMLStreamReader> {
+
+ public XMLStreamReader transform(Node source, TransformationContext context) {
+ try {
+ DOMXMLStreamReader reader = new DOMXMLStreamReader(source);
+ return new XMLDocumentStreamReader(reader);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Node.class;
+ }
+
+ public Class getTargetType() {
+ return XMLStreamReader.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java
new file mode 100644
index 0000000000..02de055c35
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.databinding.xml;
+
+import java.io.Reader;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+/**
+ * Push DOM Reader to Node
+ */
+@Service(Transformer.class)
+public class Reader2Node extends TransformerExtension<Reader, Node> implements PullTransformer<Reader, Node> {
+ private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer();
+
+ public Node transform(Reader source, TransformationContext context) {
+ try {
+ Source streamSource = new StreamSource(source);
+ DOMResult result = new DOMResult();
+ TRANSFORMER.transform(streamSource, result, context);
+ return result.getNode();
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Reader.class;
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java
new file mode 100644
index 0000000000..0a4504b3de
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java
@@ -0,0 +1,58 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.Reader;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+
+/**
+ * Transform XML string to SAX
+ */
+@Service(Transformer.class)
+public class Reader2SAX extends TransformerExtension<Reader, ContentHandler> implements
+ PushTransformer<Reader, ContentHandler> {
+ public void transform(Reader source, ContentHandler target, TransformationContext context) {
+ try {
+ new InputSource2SAX().transform(new InputSource(source), target, context);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Reader.class;
+ }
+
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java
new file mode 100644
index 0000000000..8f8f0f952e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ *
+ * 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.core.databinding.xml;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.Text;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * SAX2DOM adapter
+ */
+public class SAX2DOM implements ContentHandler, LexicalHandler {
+ public static final String EMPTYSTRING = "";
+ public static final String XML_PREFIX = "xml";
+ public static final String XMLNS_PREFIX = "xmlns";
+ public static final String XMLNS_STRING = "xmlns:";
+ public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+
+ private Node root;
+
+ private Document document;
+
+ private Node nextSibling;
+
+ private Stack<Node> nodeStk = new Stack<Node>();
+
+ private List<String> namespaceDecls;
+
+ private Node lastSibling;
+
+ public SAX2DOM() throws ParserConfigurationException {
+ this.document = DOMHelper.newDocument();
+ this.root = document;
+ }
+
+ public SAX2DOM(Node root, Node nextSibling) throws ParserConfigurationException {
+ this.root = root;
+ if (root instanceof Document) {
+ this.document = (Document)root;
+ } else if (root != null) {
+ this.document = root.getOwnerDocument();
+ } else {
+ this.document = DOMHelper.newDocument();
+ this.root = document;
+ }
+
+ this.nextSibling = nextSibling;
+ }
+
+ public SAX2DOM(Node root) throws ParserConfigurationException {
+ this(root, null);
+ }
+
+ public Node getDOM() {
+ return root;
+ }
+
+ public void characters(char[] ch, int start, int length) {
+ final Node last = (Node)nodeStk.peek();
+
+ // No text nodes can be children of root (DOM006 exception)
+ if (last != document) {
+ final String text = new String(ch, start, length);
+ if (lastSibling != null && lastSibling.getNodeType() == Node.TEXT_NODE) {
+ ((Text)lastSibling).appendData(text);
+ } else if (last == root && nextSibling != null) {
+ lastSibling = last.insertBefore(document.createTextNode(text), nextSibling);
+ } else {
+ lastSibling = last.appendChild(document.createTextNode(text));
+ }
+
+ }
+ }
+
+ public void startDocument() {
+ nodeStk.push(root);
+ }
+
+ public void endDocument() {
+ nodeStk.pop();
+ }
+
+ public void startElement(String namespace, String localName, String qName, Attributes attrs) {
+ final Element tmp = (Element)document.createElementNS(namespace, qName);
+
+ // Add namespace declarations first
+ if (namespaceDecls != null) {
+ final int nDecls = namespaceDecls.size();
+ for (int i = 0; i < nDecls; i++) {
+ final String prefix = (String)namespaceDecls.get(i++);
+
+ if (prefix == null || prefix.equals(EMPTYSTRING)) {
+ tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, (String)namespaceDecls.get(i));
+ } else {
+ tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, (String)namespaceDecls.get(i));
+ }
+ }
+ namespaceDecls.clear();
+ }
+
+ // Add attributes to element
+ final int nattrs = attrs.getLength();
+ for (int i = 0; i < nattrs; i++) {
+ if (attrs.getLocalName(i) == null) {
+ tmp.setAttribute(attrs.getQName(i), attrs.getValue(i));
+ } else {
+ tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i));
+ }
+ }
+
+ // Append this new node onto current stack node
+ Node last = (Node)nodeStk.peek();
+
+ // If the SAX2DOM is created with a non-null next sibling node,
+ // insert the result nodes before the next sibling under the root.
+ if (last == root && nextSibling != null) {
+ last.insertBefore(tmp, nextSibling);
+ } else {
+ last.appendChild(tmp);
+ }
+
+ // Push this node onto stack
+ nodeStk.push(tmp);
+ lastSibling = null;
+ }
+
+ public void endElement(String namespace, String localName, String qName) {
+ nodeStk.pop();
+ lastSibling = null;
+ }
+
+ public void startPrefixMapping(String prefix, String uri) {
+ if (namespaceDecls == null) {
+ namespaceDecls = new ArrayList<String>(2);
+ }
+ namespaceDecls.add(prefix);
+ namespaceDecls.add(uri);
+ }
+
+ public void endPrefixMapping(String prefix) {
+ // do nothing
+ }
+
+ /**
+ * This class is only used internally so this method should never be called.
+ */
+ public void ignorableWhitespace(char[] ch, int start, int length) {
+ }
+
+ /**
+ * adds processing instruction node to DOM.
+ */
+ public void processingInstruction(String target, String data) {
+ final Node last = (Node)nodeStk.peek();
+ ProcessingInstruction pi = document.createProcessingInstruction(target, data);
+ if (pi != null) {
+ if (last == root && nextSibling != null) {
+ last.insertBefore(pi, nextSibling);
+ } else {
+ last.appendChild(pi);
+ }
+
+ lastSibling = pi;
+ }
+ }
+
+ /**
+ * This class is only used internally so this method should never be called.
+ */
+ public void setDocumentLocator(Locator locator) {
+ }
+
+ /**
+ * This class is only used internally so this method should never be called.
+ */
+ public void skippedEntity(String name) {
+ }
+
+ /**
+ * Lexical Handler method to create comment node in DOM tree.
+ */
+ public void comment(char[] ch, int start, int length) {
+ final Node last = (Node)nodeStk.peek();
+ Comment comment = document.createComment(new String(ch, start, length));
+ if (comment != null) {
+ if (last == root && nextSibling != null) {
+ last.insertBefore(comment, nextSibling);
+ } else {
+ last.appendChild(comment);
+ }
+
+ lastSibling = comment;
+ }
+ }
+
+ // Lexical Handler methods- not implemented
+ public void startCDATA() {
+ }
+
+ public void endCDATA() {
+ }
+
+ public void startEntity(java.lang.String name) {
+ }
+
+ public void endDTD() {
+ }
+
+ public void endEntity(String name) {
+ }
+
+ public void startDTD(String name, String publicId, String systemId) throws SAXException {
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java
new file mode 100644
index 0000000000..79118b4a2c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java
@@ -0,0 +1,67 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tuscany.spi.databinding.DataPipe;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+import org.xml.sax.ContentHandler;
+
+@Service(Transformer.class)
+public class SAX2DOMPipe extends TransformerExtension<ContentHandler, Node> implements
+ DataPipe<ContentHandler, Node> {
+ private SAX2DOM pipe;
+
+ /**
+ *
+ */
+ public SAX2DOMPipe() {
+ super();
+ try {
+ this.pipe = new SAX2DOM();
+ } catch (ParserConfigurationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public Node getResult() {
+ return pipe.getDOM();
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ public ContentHandler getSink() {
+ return pipe;
+ }
+
+ public Class getSourceType() {
+ return ContentHandler.class;
+ }
+
+ public int getWeight() {
+ return 30;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java
new file mode 100755
index 0000000000..7db14efb39
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerFactory;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * Transform TrAX Source to Result
+ */
+@Service(org.apache.tuscany.spi.databinding.Transformer.class)
+public class Source2ResultTransformer extends TransformerExtension<Source, Result> implements
+ PushTransformer<Source, Result> {
+ private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
+
+ public void transform(Source source, Result result, TransformationContext context) {
+ try {
+ javax.xml.transform.Transformer transformer = FACTORY.newTransformer();
+ transformer.transform(source, result);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return Source.class;
+ }
+
+ public Class getTargetType() {
+ return Result.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java
new file mode 100644
index 0000000000..63fa53edb4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java
@@ -0,0 +1,256 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * Adapter that converts from StAX to SAX event streams. Currently the following
+ * SAX events are not generated:
+ * <ul>
+ * <li>ignorableWhitespace</li>
+ * <li>skippedEntity</li>
+ * <ul>
+ * Also the following StAX events are not mapped:
+ * <ul>
+ * <li>CDATA</li>
+ * <li>COMMENT</li>
+ * <li>DTD</li>
+ * <li>ENTITY_DECLARATION</li>
+ * <li>ENTITY_REFERENCE</li>
+ * <li>NOTATION_DECLARATION</li>
+ * <li>SPACE</li>
+ * </ul>
+ * StAX ATTRIBUTE events are ignored but the equivalent attributes (derived from
+ * the START_ELEMENT event) are supplied in the SAX startElement event's
+ * Attributes parameter. If the adaptor is configured to pass namespace prefixes
+ * then namespace information will also be included in the Attributes; StAX
+ * NAMESPACE events are ignored. <p/> Another issue is namespace processing. If
+ * the reader is positioned at a sub-node, we cannot capture all the in-scope
+ * namespace bindings. Therefore we cannot re-create a proper SAX event stream
+ * from a StAX parser. <p/> For example <p/> &lt;a:root xmlns:a="foo"
+ * xmlns:b="bar"&gt;&lt;b:sub&gt;a:foo&lt;/b:sub&gt;&lt;/a:root&gt; <p/> And if
+ * you are handed a parser at &lt;b:sub&gt;, then your SAX events should look
+ * like: <p/> &lt;b:sub xmlns:a="foo" xmlns:b="bar"&gt;a:foo&lt;/b:sub&gt; <p/>
+ * not: <p/> &lt;b:sub&gt;a:foo&lt;/b:sub&gt; <p/> <p/> Proposal: we change the
+ * receiver of SAX events (SDOXMLResourceImpl) so that it uses NamespaceContext
+ * to resolve prefix (as opposed to record start/endPrefixMappings and use it
+ * for resolution.)
+ *
+ * @version $Rev$ $Date$
+ */
+public class StAX2SAXAdapter {
+ private final boolean namespacePrefixes;
+
+ /**
+ * Construct a new StAX to SAX adapter that will convert a StAX event stream
+ * into a SAX event stream.
+ *
+ * @param namespacePrefixes whether xmlns attributes should be included in
+ * startElement events;
+ */
+ public StAX2SAXAdapter(boolean namespacePrefixes) {
+ this.namespacePrefixes = namespacePrefixes;
+ }
+
+ /**
+ * Pull events from the StAX stream and dispatch to the SAX ContentHandler.
+ * The StAX stream would typically be located on a START_DOCUMENT or
+ * START_ELEMENT event and when this method returns it will be located on
+ * the associated END_DOCUMENT or END_ELEMENT event. Behaviour with other
+ * start events is undefined.
+ *
+ * @param reader StAX event source to read
+ * @param handler SAX ContentHandler for processing events
+ * @throws XMLStreamException if there was a problem reading the stream
+ * @throws SAXException passed through from the ContentHandler
+ */
+ public void parse(XMLStreamReader reader, ContentHandler handler) throws XMLStreamException, SAXException {
+ handler.setDocumentLocator(new LocatorAdaptor(reader.getLocation()));
+
+ // remembers the nest level of elements to know when we are done
+ int level = 0;
+ int event = reader.getEventType();
+ while (true) {
+ switch (event) {
+ case XMLStreamConstants.START_DOCUMENT:
+ level++;
+ handler.startDocument();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ level++;
+ handleStartElement(reader, handler);
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ handler.processingInstruction(reader.getPITarget(), reader.getPIData());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ handler.characters(reader.getTextCharacters(), reader.getTextStart(), reader
+ .getTextLength());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ handleEndElement(reader, handler);
+ level--;
+ if (level == 0) {
+ return;
+ }
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ return;
+ /*
+ * uncomment to handle all events rather than just mapped
+ * ones // StAX events that are not mapped to SAX case
+ * XMLStreamConstants.COMMENT: case
+ * XMLStreamConstants.SPACE: case
+ * XMLStreamConstants.ENTITY_REFERENCE: case
+ * XMLStreamConstants.DTD: case XMLStreamConstants.CDATA:
+ * case XMLStreamConstants.NOTATION_DECLARATION: case
+ * XMLStreamConstants.ENTITY_DECLARATION: break; // StAX
+ * events handled in START_ELEMENT case
+ * XMLStreamConstants.ATTRIBUTE: case
+ * XMLStreamConstants.NAMESPACE: break; default: throw new
+ * AssertionError("Unknown StAX event: " + event);
+ */
+ }
+ event = reader.next();
+ }
+ }
+
+ private void handleStartElement(XMLStreamReader reader, ContentHandler handler) throws SAXException {
+ // send startPrefixMapping events immediately before startElement event
+ int nsCount = reader.getNamespaceCount();
+ for (int i = 0; i < nsCount; i++) {
+ String prefix = reader.getNamespacePrefix(i);
+ if (prefix == null) { // true for default namespace
+ prefix = "";
+ }
+ handler.startPrefixMapping(prefix, reader.getNamespaceURI(i));
+ }
+
+ // fire startElement
+ QName qname = reader.getName();
+ String prefix = qname.getPrefix();
+ String rawname;
+ if (prefix == null || prefix.length() == 0) {
+ rawname = qname.getLocalPart();
+ } else {
+ rawname = prefix + ':' + qname.getLocalPart();
+ }
+ Attributes attrs = getAttributes(reader);
+ handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs);
+ }
+
+ private static void handleEndElement(XMLStreamReader reader, ContentHandler handler) throws SAXException {
+ // fire endElement
+ QName qname = reader.getName();
+ handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString());
+
+ // send endPrefixMapping events immediately after endElement event
+ // we send them in the opposite order to that returned but this is not
+ // actually required by SAX
+ int nsCount = reader.getNamespaceCount();
+ for (int i = nsCount - 1; i >= 0; i--) {
+ String prefix = reader.getNamespacePrefix(i);
+ if (prefix == null) { // true for default namespace
+ prefix = "";
+ }
+ handler.endPrefixMapping(prefix);
+ }
+ }
+
+ /**
+ * Get the attributes associated with the current START_ELEMENT event.
+ *
+ * @return the StAX attributes converted to org.xml.sax.Attributes
+ */
+ private Attributes getAttributes(XMLStreamReader reader) {
+ assert reader.getEventType() == XMLStreamConstants.START_ELEMENT;
+
+ AttributesImpl attrs = new AttributesImpl();
+
+ // add namespace declarations if required
+ if (namespacePrefixes) {
+ for (int i = 0; i < reader.getNamespaceCount(); i++) {
+ String prefix = reader.getNamespacePrefix(i);
+ String uri = reader.getNamespaceURI(i);
+ attrs.addAttribute(null, prefix, "xmlns:" + prefix, "CDATA", uri);
+ }
+ }
+
+ // Regular attributes
+ for (int i = 0; i < reader.getAttributeCount(); i++) {
+ String uri = reader.getAttributeNamespace(i);
+ if (uri == null) {
+ uri = "";
+ }
+ String localName = reader.getAttributeLocalName(i);
+ String prefix = reader.getAttributePrefix(i);
+ String qname;
+ if (prefix == null || prefix.length() == 0) {
+ qname = localName;
+ } else {
+ qname = prefix + ':' + localName;
+ }
+ String type = reader.getAttributeType(i);
+ String value = reader.getAttributeValue(i);
+
+ attrs.addAttribute(uri, localName, qname, type, value);
+ }
+
+ return attrs;
+ }
+
+ /**
+ * Adaptor for mapping Locator information.
+ */
+ private static final class LocatorAdaptor implements Locator {
+ private final Location location;
+
+ private LocatorAdaptor(Location location) {
+ this.location = location;
+ }
+
+ public int getColumnNumber() {
+ return location == null ? 0 : location.getColumnNumber();
+ }
+
+ public int getLineNumber() {
+ return location == null ? 0 : location.getLineNumber();
+ }
+
+ public String getPublicId() {
+ return location == null ? "" : location.getPublicId();
+ }
+
+ public String getSystemId() {
+ return location == null ? "" : location.getSystemId();
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java
new file mode 100755
index 0000000000..5426384961
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java
@@ -0,0 +1,806 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.NoSuchElementException;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Source;
+
+public final class StAXHelper {
+ private static final XMLInputFactory INPUT_FACTORY = XMLInputFactory.newInstance();
+ private static final XMLOutputFactory OUTPUT_FACTORY = XMLOutputFactory.newInstance();
+
+ private StAXHelper() {
+ }
+
+ /**
+ * This class is derived from Apache Axis2 class org.apache.axis2.util.StreamWrapper</a>. It's used wrap a
+ * XMLStreamReader to create a XMLStreamReader representing a document and it will produce START_DOCUMENT,
+ * END_DOCUMENT events.
+ */
+ public static class XMLDocumentStreamReader implements XMLStreamReader {
+ private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper
+ // will produce
+ // END_DOCUMENT
+
+ private static final int STATE_COMPLETED = 3; // Done
+
+ private static final int STATE_INIT = 0; // The wrapper will produce
+ // START_DOCUMENT
+
+ private static final int STATE_SWITCHED = 1; // The real reader will
+ // produce events
+
+ private XMLStreamReader realReader;
+
+ private int state = STATE_INIT;
+
+ public XMLDocumentStreamReader(XMLStreamReader realReader) {
+ if (realReader == null) {
+ throw new UnsupportedOperationException("Reader cannot be null");
+ }
+
+ this.realReader = realReader;
+
+ // If the real reader is positioned at START_DOCUMENT, always use
+ // the real reader
+ if (realReader.getEventType() == START_DOCUMENT) {
+ state = STATE_SWITCHED;
+ }
+ }
+
+ public void close() throws XMLStreamException {
+ realReader.close();
+ }
+
+ public int getAttributeCount() {
+ if (isDelegating()) {
+ return realReader.getAttributeCount();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeLocalName(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeLocalName(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public QName getAttributeName(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeName(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeNamespace(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeNamespace(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributePrefix(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributePrefix(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeType(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeType(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeValue(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeValue(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeValue(String s, String s1) {
+ if (isDelegating()) {
+ return realReader.getAttributeValue(s, s1);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getCharacterEncodingScheme() {
+ return realReader.getCharacterEncodingScheme();
+ }
+
+ public String getElementText() throws XMLStreamException {
+ if (isDelegating()) {
+ return realReader.getElementText();
+ } else {
+ throw new XMLStreamException();
+ }
+ }
+
+ public String getEncoding() {
+ return realReader.getEncoding();
+ }
+
+ public int getEventType() {
+ int event = -1;
+ switch (state) {
+ case STATE_SWITCHED:
+ case STATE_COMPLETE_AT_NEXT:
+ event = realReader.getEventType();
+ break;
+ case STATE_INIT:
+ event = START_DOCUMENT;
+ break;
+ case STATE_COMPLETED:
+ event = END_DOCUMENT;
+ break;
+ }
+ return event;
+ }
+
+ public String getLocalName() {
+ if (isDelegating()) {
+ return realReader.getLocalName();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public Location getLocation() {
+ if (isDelegating()) {
+ return realReader.getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ public QName getName() {
+ if (isDelegating()) {
+ return realReader.getName();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public NamespaceContext getNamespaceContext() {
+ return realReader.getNamespaceContext();
+ }
+
+ public int getNamespaceCount() {
+ if (isDelegating()) {
+ return realReader.getNamespaceCount();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespacePrefix(int i) {
+ if (isDelegating()) {
+ return realReader.getNamespacePrefix(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespaceURI() {
+ if (isDelegating()) {
+ return realReader.getNamespaceURI();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespaceURI(int i) {
+ if (isDelegating()) {
+ return realReader.getNamespaceURI(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespaceURI(String s) {
+ if (isDelegating()) {
+ return realReader.getNamespaceURI(s);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getPIData() {
+ if (isDelegating()) {
+ return realReader.getPIData();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getPITarget() {
+ if (isDelegating()) {
+ return realReader.getPITarget();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getPrefix() {
+ if (isDelegating()) {
+ return realReader.getPrefix();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public Object getProperty(String s) throws IllegalArgumentException {
+ if (isDelegating()) {
+ return realReader.getProperty(s);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public String getText() {
+ if (isDelegating()) {
+ return realReader.getText();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public char[] getTextCharacters() {
+ if (isDelegating()) {
+ return realReader.getTextCharacters();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException {
+ if (isDelegating()) {
+ return realReader.getTextCharacters(i, chars, i1, i2);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextLength() {
+ if (isDelegating()) {
+ return realReader.getTextLength();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextStart() {
+ if (isDelegating()) {
+ return realReader.getTextStart();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getVersion() {
+ if (isDelegating()) {
+ return realReader.getVersion();
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasName() {
+ if (isDelegating()) {
+ return realReader.hasName();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean hasNext() throws XMLStreamException {
+ if (state == STATE_COMPLETE_AT_NEXT) {
+ return true;
+ } else if (state == STATE_COMPLETED) {
+ return false;
+ } else if (state == STATE_SWITCHED) {
+ return realReader.hasNext();
+ } else {
+ return true;
+ }
+ }
+
+ public boolean hasText() {
+ if (isDelegating()) {
+ return realReader.hasText();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isAttributeSpecified(int i) {
+ if (isDelegating()) {
+ return realReader.isAttributeSpecified(i);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isCharacters() {
+ if (isDelegating()) {
+ return realReader.isCharacters();
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isDelegating() {
+ return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT;
+ }
+
+ public boolean isEndElement() {
+ if (isDelegating()) {
+ return realReader.isEndElement();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStandalone() {
+ if (isDelegating()) {
+ return realReader.isStandalone();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStartElement() {
+ if (isDelegating()) {
+ return realReader.isStartElement();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isWhiteSpace() {
+ if (isDelegating()) {
+ return realReader.isWhiteSpace();
+ } else {
+ return false;
+ }
+ }
+
+ public int next() throws XMLStreamException {
+ int returnEvent;
+
+ switch (state) {
+ case STATE_SWITCHED:
+ returnEvent = realReader.next();
+ if (returnEvent == END_DOCUMENT) {
+ state = STATE_COMPLETED;
+ } else if (!realReader.hasNext()) {
+ state = STATE_COMPLETE_AT_NEXT;
+ }
+ break;
+ case STATE_INIT:
+ state = STATE_SWITCHED;
+ returnEvent = realReader.getEventType();
+ break;
+ case STATE_COMPLETE_AT_NEXT:
+ state = STATE_COMPLETED;
+ returnEvent = END_DOCUMENT;
+ break;
+ case STATE_COMPLETED:
+ // oops - no way we can go beyond this
+ throw new NoSuchElementException("End of stream has reached.");
+ default:
+ throw new UnsupportedOperationException();
+ }
+
+ return returnEvent;
+ }
+
+ public int nextTag() throws XMLStreamException {
+ if (isDelegating()) {
+ return realReader.nextTag();
+ } else {
+ throw new XMLStreamException();
+ }
+ }
+
+ public void require(int i, String s, String s1) throws XMLStreamException {
+ if (isDelegating()) {
+ realReader.require(i, s, s1);
+ }
+ }
+
+ public boolean standaloneSet() {
+ if (isDelegating()) {
+ return realReader.standaloneSet();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public static interface XMLFragmentStreamReader extends XMLStreamReader {
+
+ // this will help to handle Text within the current element.
+ // user should pass the element text to the property list as this
+ // ELEMENT_TEXT as the key. This key deliberately has a space in it
+ // so that it is not a valid XML name
+ String ELEMENT_TEXT = "Element Text";
+
+ /**
+ * Initiate the parser - this will do whatever the needed tasks to initiate the parser and must be called before
+ * attempting any specific parsing using this parser
+ */
+ void init();
+
+ /**
+ * Extra method to query the state of the pullparser
+ */
+ boolean isEndOfFragment();
+
+ /**
+ * add the parent namespace context to this parser
+ */
+ void setParentNamespaceContext(NamespaceContext nsContext);
+ }
+
+ /**
+ * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps into the XMLStreamWriter
+ */
+ public static class XMLStreamSerializer implements XMLStreamConstants {
+ public static final String NAMESPACE_PREFIX = "ns";
+ private static int namespaceSuffix;
+
+ /*
+ * The behavior of the serializer is such that it returns when it
+ * encounters the starting element for the second time. The depth
+ * variable tracks the depth of the serilizer and tells it when to
+ * return. Note that it is assumed that this serialization starts on an
+ * Element.
+ */
+
+ /**
+ * Field depth
+ */
+ private int depth;
+
+ /**
+ * Generates a unique namespace prefix that is not in the scope of the NamespaceContext
+ *
+ * @param nsCtxt
+ * @return string
+ */
+ private String generateUniquePrefix(NamespaceContext nsCtxt) {
+ String prefix = NAMESPACE_PREFIX + namespaceSuffix++;
+ // null should be returned if the prefix is not bound!
+ while (nsCtxt.getNamespaceURI(prefix) != null) {
+ prefix = NAMESPACE_PREFIX + namespaceSuffix++;
+ }
+
+ return prefix;
+ }
+
+ /**
+ * Method serialize.
+ *
+ * @param node
+ * @param writer
+ * @throws XMLStreamException
+ */
+ public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException {
+ serializeNode(node, writer);
+ }
+
+ /**
+ * @param reader
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer)
+ throws XMLStreamException {
+ int count = reader.getAttributeCount();
+ String prefix;
+ String namespaceName;
+ String writerPrefix;
+ for (int i = 0; i < count; i++) {
+ prefix = reader.getAttributePrefix(i);
+ namespaceName = reader.getAttributeNamespace(i);
+ /*
+ * Due to parser implementations returning null as the namespace
+ * URI (for the empty namespace) we need to make sure that we
+ * deal with a namespace name that is not null. The best way to
+ * work around this issue is to set the namespace uri to "" if
+ * it is null
+ */
+ if (namespaceName == null) {
+ namespaceName = "";
+ }
+
+ writerPrefix = writer.getNamespaceContext().getPrefix(namespaceName);
+
+ if (!"".equals(namespaceName)) {
+ // prefix has already being declared but this particular
+ // attrib has a
+ // no prefix attached. So use the prefix provided by the
+ // writer
+ if (writerPrefix != null && (prefix == null || prefix.equals(""))) {
+ writer.writeAttribute(writerPrefix,
+ namespaceName,
+ reader.getAttributeLocalName(i),
+ reader.getAttributeValue(i));
+
+ // writer prefix is available but different from the
+ // current
+ // prefix of the attrib. We should be decalring the new
+ // prefix
+ // as a namespace declaration
+ } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) {
+ writer.writeNamespace(prefix, namespaceName);
+ writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader
+ .getAttributeValue(i));
+
+ // prefix is null (or empty), but the namespace name is
+ // valid! it has not
+ // being written previously also. So we need to generate
+ // a prefix
+ // here
+ } else if (prefix == null || prefix.equals("")) {
+ prefix = generateUniquePrefix(writer.getNamespaceContext());
+ writer.writeNamespace(prefix, namespaceName);
+ writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader
+ .getAttributeValue(i));
+ } else {
+ writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader
+ .getAttributeValue(i));
+ }
+ } else {
+ // empty namespace is equal to no namespace!
+ writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
+ }
+
+ }
+ }
+
+ /**
+ * Method serializeCData.
+ *
+ * @param reader
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer)
+ throws XMLStreamException {
+ writer.writeCData(reader.getText());
+ }
+
+ /**
+ * Method serializeComment.
+ *
+ * @param reader
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer)
+ throws XMLStreamException {
+ writer.writeComment(reader.getText());
+ }
+
+ /**
+ * @param reader
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer)
+ throws XMLStreamException {
+ String prefix = reader.getPrefix();
+ String nameSpaceName = reader.getNamespaceURI();
+ if (nameSpaceName != null) {
+ String writerPrefix = writer.getPrefix(nameSpaceName);
+ if (writerPrefix != null) {
+ writer.writeStartElement(nameSpaceName, reader.getLocalName());
+ } else {
+ if (prefix != null) {
+ writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName);
+ writer.writeNamespace(prefix, nameSpaceName);
+ writer.setPrefix(prefix, nameSpaceName);
+ } else {
+ writer.writeStartElement(nameSpaceName, reader.getLocalName());
+ writer.writeDefaultNamespace(nameSpaceName);
+ writer.setDefaultNamespace(nameSpaceName);
+ }
+ }
+ } else {
+ writer.writeStartElement(reader.getLocalName());
+ }
+
+ // add the namespaces
+ int count = reader.getNamespaceCount();
+ String namespacePrefix;
+ for (int i = 0; i < count; i++) {
+ namespacePrefix = reader.getNamespacePrefix(i);
+ if (namespacePrefix != null && namespacePrefix.length() == 0) {
+ continue;
+ }
+
+ serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer);
+ }
+
+ // add attributes
+ serializeAttributes(reader, writer);
+
+ }
+
+ /**
+ * Method serializeEndElement.
+ *
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException {
+ writer.writeEndElement();
+ }
+
+ /**
+ * Method serializeNamespace.
+ *
+ * @param prefix
+ * @param uri
+ * @param writer
+ * @throws XMLStreamException
+ */
+ private void serializeNamespace(String prefix, String uri, XMLStreamWriter writer)
+ throws XMLStreamException {
+ String prefix1 = writer.getPrefix(uri);
+ if (prefix1 == null) {
+ writer.writeNamespace(prefix, uri);
+ writer.setPrefix(prefix, uri);
+ }
+ }
+
+ /**
+ * Method serializeNode.
+ *
+ * @param reader
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer)
+ throws XMLStreamException {
+ // TODO We get the StAXWriter at this point and uses it hereafter
+ // assuming that this is the only entry point
+ // to this class.
+ // If there can be other classes calling methodes of this we might
+ // need to change methode signatures to
+ // OMOutputer
+ while (reader.hasNext()) {
+ int event = reader.next();
+ if (event == START_ELEMENT) {
+ serializeElement(reader, writer);
+ depth++;
+ } else if (event == ATTRIBUTE) {
+ serializeAttributes(reader, writer);
+ } else if (event == CHARACTERS) {
+ serializeText(reader, writer);
+ } else if (event == COMMENT) {
+ serializeComment(reader, writer);
+ } else if (event == CDATA) {
+ serializeCData(reader, writer);
+ } else if (event == END_ELEMENT) {
+ serializeEndElement(writer);
+ depth--;
+ } else if (event == START_DOCUMENT) {
+ depth++; // if a start document is found then increment
+ // the depth
+ } else if (event == END_DOCUMENT) {
+ if (depth != 0) {
+ depth--; // for the end document - reduce the depth
+ }
+ try {
+ serializeEndElement(writer);
+ } catch (Exception e) {
+ // TODO: log exceptions
+ }
+ }
+ if (depth == 0) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * @param reader
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer)
+ throws XMLStreamException {
+ writer.writeCharacters(reader.getText());
+ }
+ }
+
+ public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException {
+ return INPUT_FACTORY.createXMLStreamReader(inputStream);
+ }
+
+ public static XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException {
+ return INPUT_FACTORY.createXMLStreamReader(reader);
+ }
+
+ public static XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException {
+ return INPUT_FACTORY.createXMLStreamReader(source);
+ }
+
+ public static XMLStreamReader createXMLStreamReader(String string) throws XMLStreamException {
+ StringReader reader = new StringReader(string);
+ return createXMLStreamReader(reader);
+ }
+
+ public static String save(XMLStreamReader reader) throws XMLStreamException {
+ StringWriter writer = new StringWriter();
+ save(reader, writer);
+ return writer.toString();
+ }
+
+ public static void save(XMLStreamReader reader, OutputStream outputStream) throws XMLStreamException {
+ XMLStreamSerializer serializer = new XMLStreamSerializer();
+ XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(outputStream);
+ serializer.serialize(reader, streamWriter);
+ streamWriter.flush();
+ }
+
+ public static void save(XMLStreamReader reader, Writer writer) throws XMLStreamException {
+ XMLStreamSerializer serializer = new XMLStreamSerializer();
+ XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(writer);
+ serializer.serialize(reader, streamWriter);
+ streamWriter.flush();
+ }
+
+ public static void save(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
+ XMLStreamSerializer serializer = new XMLStreamSerializer();
+ serializer.serialize(reader, writer);
+ writer.flush();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java
new file mode 100755
index 0000000000..d0b6ce07f2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java
@@ -0,0 +1,57 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.tuscany.spi.databinding.DataPipe;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+
+@Service(Transformer.class)
+public class StreamDataPipe extends TransformerExtension<OutputStream, InputStream> implements
+ DataPipe<OutputStream, InputStream> {
+
+ private ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ public InputStream getResult() {
+ return new ByteArrayInputStream(outputStream.toByteArray());
+ }
+
+ public Class getTargetType() {
+ return InputStream.class;
+ }
+
+ public int getWeight() {
+ return 50;
+ }
+
+ public OutputStream getSink() {
+ return outputStream;
+ }
+
+ public Class getSourceType() {
+ return OutputStream.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java
new file mode 100755
index 0000000000..3f878a07b9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+
+@Service(Transformer.class)
+public class String2Node extends TransformerExtension<String, Node> implements PullTransformer<String, Node> {
+
+ public Node transform(String source, TransformationContext context) {
+ try {
+ DocumentBuilder builder = DOMHelper.newDocumentBuilder();
+ InputSource inputSource = new InputSource(new StringReader(source));
+ return builder.parse(inputSource);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return String.class;
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ public int getWeight() {
+ return 50;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java
new file mode 100644
index 0000000000..50ea110b17
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java
@@ -0,0 +1,59 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.StringReader;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+
+/**
+ * Transform XML string to SAX
+ */
+@Service(Transformer.class)
+public class String2SAX extends TransformerExtension<String, ContentHandler> implements
+ PushTransformer<String, ContentHandler> {
+
+ public void transform(String source, ContentHandler target, TransformationContext context) {
+ try {
+ new InputSource2SAX().transform(new InputSource(new StringReader(source)), target, context);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return String.class;
+ }
+
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java
new file mode 100755
index 0000000000..9793cc3f7e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.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.core.databinding.xml;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+
+@Service(Transformer.class)
+public class String2XMLStreamReader extends TransformerExtension<String, XMLStreamReader> implements
+ PullTransformer<String, XMLStreamReader> {
+
+ public XMLStreamReader transform(String source, TransformationContext context) {
+ try {
+ return StAXHelper.createXMLStreamReader(source);
+ } catch (XMLStreamException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return String.class;
+ }
+
+ public Class getTargetType() {
+ return XMLStreamReader.class;
+ }
+
+ public int getWeight() {
+ return 50;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java
new file mode 100755
index 0000000000..c66d0fd934
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java
@@ -0,0 +1,56 @@
+/*
+ * 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.core.databinding.xml;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.apache.tuscany.spi.databinding.DataPipe;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+
+@Service(Transformer.class)
+public class Writer2ReaderDataPipe extends TransformerExtension<Writer, Reader> implements DataPipe<Writer, Reader> {
+
+ private StringWriter writer = new StringWriter();
+
+ public Reader getResult() {
+ return new StringReader(writer.toString());
+ }
+
+ public Class getTargetType() {
+ return Reader.class;
+ }
+
+ public int getWeight() {
+ return 50;
+ }
+
+ public Writer getSink() {
+ return writer;
+ }
+
+ public Class getSourceType() {
+ return Writer.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java
new file mode 100644
index 0000000000..6ecaa85be4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java
@@ -0,0 +1,62 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+/**
+ * Transform DOM Node to XML XMLStreamReader
+ */
+@Service(Transformer.class)
+public class XMLStreamReader2Node extends TransformerExtension<XMLStreamReader, Node> implements
+ PullTransformer<XMLStreamReader, Node> {
+ private SAX2DOMPipe pipe = new SAX2DOMPipe();
+
+ private XMLStreamReader2SAX stax2sax = new XMLStreamReader2SAX();
+
+ public Node transform(XMLStreamReader source, TransformationContext context) {
+ try {
+ stax2sax.transform(source, pipe.getSink(), context);
+ return pipe.getResult();
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return XMLStreamReader.class;
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java
new file mode 100644
index 0000000000..0c6f0b8df7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.databinding.PushTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+import org.xml.sax.ContentHandler;
+
+/**
+ * XMLStreamReader to SAX events
+ */
+@Service(Transformer.class)
+public class XMLStreamReader2SAX extends TransformerExtension<XMLStreamReader, ContentHandler> implements
+ PushTransformer<XMLStreamReader, ContentHandler> {
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.PushTransformer#getSourceType()
+ */
+ public Class getTargetType() {
+ return ContentHandler.class;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.PushTransformer#getSourceType()
+ */
+ public Class getSourceType() {
+ return XMLStreamReader.class;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.PushTransformer#getWeight()
+ */
+ public int getWeight() {
+ return 20;
+ }
+
+ /**
+ * @see org.apache.tuscany.spi.databinding.PushTransformer#transform(java.lang.Object,
+ * java.lang.Object,
+ * org.apache.tuscany.spi.databinding.TransformationContext)
+ */
+ public void transform(XMLStreamReader source, ContentHandler sink, TransformationContext context) {
+ StAX2SAXAdapter adapter = new StAX2SAXAdapter(false);
+ try {
+ adapter.parse(source, sink);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java
new file mode 100755
index 0000000000..85ac7b5af6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.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.core.databinding.xml;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.databinding.PullTransformer;
+import org.apache.tuscany.spi.databinding.TransformationContext;
+import org.apache.tuscany.spi.databinding.TransformationException;
+import org.apache.tuscany.spi.databinding.Transformer;
+import org.apache.tuscany.spi.databinding.extension.TransformerExtension;
+import org.osoa.sca.annotations.Service;
+
+@Service(Transformer.class)
+public class XMLStreamReader2String extends TransformerExtension<XMLStreamReader, String> implements
+ PullTransformer<XMLStreamReader, String> {
+
+ public String transform(XMLStreamReader source, TransformationContext context) {
+ try {
+ return StAXHelper.save(source);
+ } catch (XMLStreamException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public Class getSourceType() {
+ return XMLStreamReader.class;
+ }
+
+ public Class getTargetType() {
+ return String.class;
+ }
+
+ public int getWeight() {
+ return 40;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java
new file mode 100644
index 0000000000..39e9362524
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java
@@ -0,0 +1,33 @@
+/*
+ * 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.core.databinding.xml;
+
+import org.apache.tuscany.spi.databinding.extension.DataBindingExtension;
+
+/**
+ * A DataBinding for the XML string
+ */
+public class XMLStringDataBinding extends DataBindingExtension {
+ public static final String NAME = String.class.getName();
+
+ public XMLStringDataBinding() {
+ super(NAME, String.class);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java
new file mode 100644
index 0000000000..8d24047781
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java
@@ -0,0 +1,80 @@
+/*
+ * 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.core.deployer;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+
+/**
+ * Base class for DeploymentContext implementations.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractDeploymentContext implements DeploymentContext {
+ private final URI componentId;
+ private boolean autowire;
+ private final ClassLoader classLoader;
+ private final URL scdlLocation;
+ private final Map<URI, Component> components = new HashMap<URI, Component>();
+
+ /**
+ * Constructor defining properties of this context.
+ *
+ * @param classLoader the classloader for loading application resources
+ * @param scdlLocation the location of the SCDL defining this composite
+ * @param componentId the id of the component being deployed
+ * @param autowire if autowire is enabled
+ */
+ protected AbstractDeploymentContext(ClassLoader classLoader, URL scdlLocation, URI componentId, boolean autowire) {
+ this.classLoader = classLoader;
+ this.scdlLocation = scdlLocation;
+ this.componentId = componentId;
+ this.autowire = autowire;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public URL getScdlLocation() {
+ return scdlLocation;
+ }
+
+ public URI getComponentId() {
+ return componentId;
+ }
+
+ public boolean isAutowire() {
+ return autowire;
+ }
+
+ public void setAutowire(boolean autowire) {
+ this.autowire = autowire;
+ }
+
+ @Deprecated
+ public Map<URI, Component> getComponents() {
+ return components;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java
new file mode 100644
index 0000000000..de523cee78
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java
@@ -0,0 +1,68 @@
+/*
+ * 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.core.deployer;
+
+import java.net.URI;
+import java.net.URL;
+import javax.xml.stream.XMLInputFactory;
+
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+
+/**
+ * An holder that can be used during the load process to store information that is not part of the logical assembly
+ * model. This should be regarded as transient and references to this context should not be stored inside the model.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ChildDeploymentContext extends AbstractDeploymentContext {
+ private final DeploymentContext parent;
+
+ /**
+ * Constructor defining properties of this context.
+ *
+ * @param parent the parent of this context
+ * @param classLoader the classloader for loading application resources
+ * @param scdlLocation the location of the SCDL defining this composite
+ * @param componentId the id of the component being deployed
+ * @param autowire if autowire is enabled
+ */
+ public ChildDeploymentContext(DeploymentContext parent,
+ ClassLoader classLoader,
+ URL scdlLocation,
+ URI componentId,
+ boolean autowire) {
+ super(classLoader, scdlLocation, componentId, autowire);
+ assert parent != null;
+ this.parent = parent;
+ }
+
+ public DeploymentContext getParent() {
+ return parent;
+ }
+
+ public XMLInputFactory getXmlFactory() {
+ return parent.getXmlFactory();
+ }
+
+ public ScopeContainer getCompositeScope() {
+ return parent.getCompositeScope();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java
new file mode 100644
index 0000000000..1524a36b75
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.core.deployer;
+
+import java.util.Collection;
+import javax.xml.stream.XMLInputFactory;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.builder.Builder;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.BuilderInstantiationException;
+import org.apache.tuscany.spi.builder.BuilderRegistry;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.ScopeContainerMonitor;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.event.RuntimeEventListener;
+import org.apache.tuscany.spi.loader.Loader;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.resolver.ResolutionException;
+
+import org.apache.tuscany.api.annotation.Monitor;
+import org.apache.tuscany.core.component.ComponentManager;
+import org.apache.tuscany.core.component.event.ComponentStop;
+import org.apache.tuscany.core.component.scope.CompositeScopeContainer;
+import org.apache.tuscany.core.resolver.AutowireResolver;
+
+/**
+ * Default implementation of Deployer.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DeployerImpl implements Deployer {
+ private XMLInputFactory xmlFactory;
+ private Builder builder;
+ private ScopeContainerMonitor monitor;
+ private Loader loader;
+ private AutowireResolver resolver;
+ private Connector connector;
+ private ComponentManager componentManager;
+
+ public DeployerImpl(XMLInputFactory xmlFactory,
+ Loader loader,
+ Builder builder,
+ ComponentManager componentManager,
+ AutowireResolver resolver,
+ Connector connector) {
+ this.xmlFactory = xmlFactory;
+ this.loader = loader;
+ this.builder = builder;
+ this.componentManager = componentManager;
+ this.resolver = resolver;
+ this.connector = connector;
+ }
+
+ public DeployerImpl() {
+ xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ }
+
+ @Reference
+ public void setLoader(LoaderRegistry loader) {
+ this.loader = loader;
+ }
+
+ @Reference
+ public void setBuilder(BuilderRegistry builder) {
+ this.builder = builder;
+ }
+
+ @Monitor
+ public void setMonitor(ScopeContainerMonitor monitor) {
+ this.monitor = monitor;
+ }
+
+ @Reference
+ public void setResolver(AutowireResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ @Reference
+ public void setConnector(Connector connector) {
+ this.connector = connector;
+ }
+
+ @Reference
+ public void setComponentManager(ComponentManager componentManager) {
+ this.componentManager = componentManager;
+ }
+
+ public <I extends Implementation<?>> Collection<Component> deploy(Component parent,
+ ComponentDefinition<I> componentDefinition)
+ throws LoaderException, BuilderException, ResolutionException {
+ final ScopeContainer scopeContainer = new CompositeScopeContainer(monitor);
+ scopeContainer.start();
+ DeploymentContext deploymentContext =
+ new RootDeploymentContext(null, null, componentDefinition.getUri(), xmlFactory, scopeContainer, false);
+ // load the model
+ load(parent, componentDefinition, deploymentContext);
+ // resolve autowires
+ resolver.resolve(null, componentDefinition);
+ // build runtime artifacts
+ Component component = (Component) build(parent, componentDefinition, deploymentContext);
+ // create a listener so the scope container is shutdown when the top-level composite stops
+ RuntimeEventListener listener = new RuntimeEventListener() {
+ public void onEvent(Event event) {
+ scopeContainer.onEvent(event);
+ if (event instanceof ComponentStop) {
+ scopeContainer.stop();
+ }
+ }
+ };
+ component.addListener(listener);
+
+ Collection<Component> components = deploymentContext.getComponents().values();
+ for (Component toRegister : components) {
+ try {
+ componentManager.register(toRegister);
+ } catch (RegistrationException e) {
+ throw new BuilderInstantiationException("Error registering component", e);
+ }
+ }
+ connector.connect(componentDefinition);
+ return components;
+ }
+
+ /**
+ * Load the componentDefinition type information for the componentDefinition being deployed. For a typical
+ * deployment this will result in the SCDL definition being loaded.
+ *
+ * @param componentDefinition the componentDefinition being deployed
+ * @param deploymentContext the current deployment context
+ */
+ protected <I extends Implementation<?>> void load(Component parent,
+ ComponentDefinition<I> componentDefinition,
+ DeploymentContext deploymentContext) throws LoaderException {
+ loader.loadComponentType(componentDefinition.getImplementation(), deploymentContext);
+ }
+
+ /**
+ * Build the runtime context for a loaded componentDefinition.
+ *
+ * @param parent the context that will be the parent of the new sub-context
+ * @param componentDefinition the componentDefinition being deployed
+ * @param deploymentContext the current deployment context
+ * @return the new runtime context
+ */
+ protected <I extends Implementation<?>> SCAObject build(Component parent,
+ ComponentDefinition<I> componentDefinition,
+ DeploymentContext deploymentContext)
+ throws BuilderException {
+ return builder.build(componentDefinition, deploymentContext);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java
new file mode 100644
index 0000000000..673cd675fd
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.deployer;
+
+import java.net.URI;
+import java.net.URL;
+import javax.xml.stream.XMLInputFactory;
+
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+
+/**
+ * A holder that can be used during the load process to store information that is not part of the logical assembly
+ * model. This should be regarded as transient and references to this context should not be stored inside the model.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RootDeploymentContext extends AbstractDeploymentContext {
+ private final XMLInputFactory xmlFactory;
+ private final ScopeContainer scopeContainer;
+
+ /**
+ * Constructor defining properties of this context.
+ *
+ * @param classLoader the classloader for loading application resources
+ * @param scdlLocation the location of the SCDL defining this composite
+ * @param componentId the id of the component being deployed
+ * @param xmlFactory a factory that can be used to obtain an StAX XMLStreamReader
+ * @param scopeContainer the scope context representing this deployment's COMPOSITE scope
+ * @param autowire if autowire is enabled
+ */
+ public RootDeploymentContext(ClassLoader classLoader,
+ URL scdlLocation,
+ URI componentId,
+ XMLInputFactory xmlFactory,
+ ScopeContainer scopeContainer,
+ boolean autowire) {
+ super(classLoader, scdlLocation, componentId, autowire);
+ this.xmlFactory = xmlFactory;
+ this.scopeContainer = scopeContainer;
+ }
+
+ public DeploymentContext getParent() {
+ return null;
+ }
+
+ public XMLInputFactory getXmlFactory() {
+ return xmlFactory;
+ }
+
+ public ScopeContainer getCompositeScope() {
+ return scopeContainer;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java
new file mode 100644
index 0000000000..d1ff543a34
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java
@@ -0,0 +1,145 @@
+/*
+ * 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.core.deployer.federation;
+
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.core.component.ComponentManager;
+import org.apache.tuscany.core.marshaller.PhysicalChangeSetMarshaller;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.builder.physical.PhysicalComponentBuilderRegistry;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.marshaller.ModelMarshallerRegistry;
+import org.apache.tuscany.spi.model.physical.PhysicalChangeSet;
+import org.apache.tuscany.spi.model.physical.PhysicalComponentDefinition;
+import org.apache.tuscany.spi.model.physical.PhysicalWireDefinition;
+import org.apache.tuscany.spi.services.discovery.DiscoveryService;
+import org.apache.tuscany.spi.services.discovery.RequestListener;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * Federated deployer that deploys components in response to asynchronous messages from the federated domain.
+ *
+ * @version $Revision$ $Date$
+ */
+public class FederatedDeployer implements RequestListener {
+
+ /**
+ * Marshaller registry.
+ */
+ private ModelMarshallerRegistry marshallerRegistry;
+
+ /**
+ * Physical component builder registry.
+ */
+ private PhysicalComponentBuilderRegistry builderRegistry;
+
+ /**
+ * Component manager.
+ */
+ private ComponentManager componentManager;
+
+ /**
+ * Connector.
+ */
+ private Connector connector;
+
+ /**
+ * Deploys the component.
+ *
+ * @param content SCDL content.
+ * @return Response to the request message.
+ * <p/>
+ * TODO Handle response messages.
+ */
+ public XMLStreamReader onRequest(XMLStreamReader content) {
+
+ try {
+
+ final PhysicalChangeSet changeSet = (PhysicalChangeSet) marshallerRegistry.unmarshall(content);
+
+ for (PhysicalComponentDefinition pcd : changeSet.getComponentDefinitions()) {
+ final Component component = builderRegistry.build(pcd);
+ componentManager.register(component);
+ component.start();
+ }
+ for (PhysicalWireDefinition pwd : changeSet.getWireDefinitions()) {
+ connector.connect(pwd);
+ }
+
+ } catch (MarshallException ex) {
+ return null;
+ } catch (BuilderException ex) {
+ return null;
+ } catch (RegistrationException ex) {
+ return null;
+ }
+
+ return null;
+ }
+
+ /**
+ * Injects the discovery service.
+ * @param discoveryService Discovery service to be injected.
+ */
+ @Reference
+ public void setDiscoveryService(DiscoveryService discoveryService) {
+ discoveryService.registerRequestListener(PhysicalChangeSetMarshaller.QNAME, this);
+ }
+
+ /**
+ * Injects the model marshaller registry.
+ * @param marshallerRegistry Marshaller registry.
+ */
+ @Reference
+ public void setMarshallerRegistry(ModelMarshallerRegistry marshallerRegistry) {
+ this.marshallerRegistry = marshallerRegistry;
+ }
+
+ /**
+ * Injects the builder registry.
+ * @param builderRegistry Builder registry.
+ */
+ @Reference
+ public void setBuilderRegistry(PhysicalComponentBuilderRegistry builderRegistry) {
+ this.builderRegistry = builderRegistry;
+ }
+
+ /**
+ * Injects the component manager.
+ * @param componentManager Component manager.
+ */
+ @Reference
+ public void setComponentManager(ComponentManager componentManager) {
+ this.componentManager = componentManager;
+ }
+
+ /**
+ * Injects the connector.
+ * @param connector Connector.
+ */
+ @Reference
+ public void setConnector(Connector connector) {
+ this.connector = connector;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java
new file mode 100644
index 0000000000..f52bd4cfb1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.idl.java;
+
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+
+/**
+ * Denotes an illegal callback interface
+ *
+ * @version $Rev$ $Date$
+ */
+
+public class IllegalCallbackException extends InvalidServiceContractException {
+
+ public IllegalCallbackException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java
new file mode 100644
index 0000000000..e2169d8978
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java
@@ -0,0 +1,114 @@
+/*
+ * 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.core.idl.java;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
+import org.apache.tuscany.spi.idl.java.JavaServiceContract;
+import org.apache.tuscany.spi.loader.InvalidValueException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.ModelObject;
+
+/**
+ * Loads a Java interface definition from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class InterfaceJavaLoader extends LoaderExtension<JavaServiceContract> {
+ public static final QName INTERFACE_JAVA = new QName(SCA_NS, "interface.java");
+
+ private final JavaInterfaceProcessorRegistry interfaceRegsitry;
+
+ @Constructor({"registry", "interfaceRegsitry"})
+ public InterfaceJavaLoader(@Reference LoaderRegistry registry,
+ @Reference JavaInterfaceProcessorRegistry interfaceRegistry) {
+ super(registry);
+ this.interfaceRegsitry = interfaceRegistry;
+ }
+
+ public QName getXMLType() {
+ return INTERFACE_JAVA;
+ }
+
+ public JavaServiceContract load(
+ ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ assert INTERFACE_JAVA.equals(reader.getName());
+ String conversationalAttr = reader.getAttributeValue(null, "conversational");
+ boolean conversational = Boolean.parseBoolean(conversationalAttr);
+ String name = reader.getAttributeValue(null, "interface");
+ if (name == null) {
+ // allow "class" as well as seems to be a common mistake
+ name = reader.getAttributeValue(null, "class");
+ }
+ if (name == null) {
+ throw new InvalidValueException("interface name not supplied");
+ }
+ Class<?> interfaceClass = LoaderUtil.loadClass(name, deploymentContext.getClassLoader());
+
+ name = reader.getAttributeValue(null, "callbackInterface");
+ Class<?> callbackClass = (name != null) ? LoaderUtil.loadClass(name, deploymentContext.getClassLoader()) : null;
+
+ Map<Class<?>, ModelObject> extensions = new HashMap<Class<?>, ModelObject>();
+ while (true) {
+ int event = reader.next();
+ if (event == XMLStreamConstants.START_ELEMENT) {
+ ModelObject mo = registry.load(null, reader, deploymentContext);
+ if (mo != null) {
+ extensions.put(mo.getClass(), mo);
+ }
+ } else if (event == XMLStreamConstants.END_ELEMENT && reader.getName().equals(INTERFACE_JAVA)) {
+ break;
+ }
+ }
+ JavaServiceContract serviceContract;
+ try {
+ serviceContract = interfaceRegsitry.introspect(interfaceClass, callbackClass);
+ } catch (InvalidServiceContractException e) {
+ throw new LoaderException(interfaceClass.getName(), e);
+ }
+
+ // Set databinding from the SCDL extension <databinding>
+ DataType<?> dataType = (DataType<?>) extensions.get(DataType.class);
+ if (dataType != null) {
+ serviceContract.setDataBinding(dataType.getDataBinding());
+ }
+ serviceContract.getExtensions().putAll(extensions);
+ serviceContract.setConversational(conversational);
+ return serviceContract;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java
new file mode 100644
index 0000000000..ea64af75b6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java
@@ -0,0 +1,156 @@
+/*
+ * 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.core.idl.java;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Conversational;
+import org.osoa.sca.annotations.EndsConversation;
+import org.osoa.sca.annotations.OneWay;
+import org.osoa.sca.annotations.Remotable;
+
+import org.apache.tuscany.spi.idl.InvalidConversationalOperationException;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.idl.OverloadedOperationException;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessor;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
+import org.apache.tuscany.spi.idl.java.JavaServiceContract;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+import static org.apache.tuscany.spi.model.Operation.CONVERSATION_END;
+import static org.apache.tuscany.spi.model.Operation.NO_CONVERSATION;
+
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName;
+
+/**
+ * Default implementation of an InterfaceJavaIntrospector.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaInterfaceProcessorRegistryImpl implements JavaInterfaceProcessorRegistry {
+ public static final String IDL_INPUT = "idl:input";
+
+ private static final String UNKNOWN_DATABINDING = null;
+
+ private List<JavaInterfaceProcessor> processors = new ArrayList<JavaInterfaceProcessor>();
+
+ public JavaInterfaceProcessorRegistryImpl() {
+ }
+
+ public void registerProcessor(JavaInterfaceProcessor processor) {
+ processors.add(processor);
+ }
+
+ public void unregisterProcessor(JavaInterfaceProcessor processor) {
+ processors.remove(processor);
+ }
+
+ public <T> JavaServiceContract introspect(Class<T> type) throws InvalidServiceContractException {
+ Class<?> callbackClass = null;
+ Callback callback = type.getAnnotation(Callback.class);
+ if (callback != null && !Void.class.equals(callback.value())) {
+ callbackClass = callback.value();
+ } else if (callback != null && Void.class.equals(callback.value())) {
+ throw new IllegalCallbackException("No callback interface specified on annotation", type.getName());
+ }
+ return introspect(type, callbackClass);
+ }
+
+ public <I, C> JavaServiceContract introspect(Class<I> type, Class<C> callback)
+ throws InvalidServiceContractException {
+ JavaServiceContract contract = new JavaServiceContract();
+ contract.setInterfaceName(getBaseName(type));
+ contract.setInterfaceClass(type);
+ boolean remotable = type.isAnnotationPresent(Remotable.class);
+ contract.setRemotable(remotable);
+ //Scope interactionScope = type.getAnnotation(Scope.class);
+ boolean conversational = type.isAnnotationPresent(Conversational.class);
+ contract.setConversational(conversational);
+ contract.setOperations(getOperations(type, remotable, conversational));
+
+ if (callback != null) {
+ contract.setCallbackName(getBaseName(callback));
+ contract.setCallbackClass(callback);
+ contract.setCallbackOperations(getOperations(callback, remotable, conversational));
+ }
+
+ for (JavaInterfaceProcessor processor : processors) {
+ processor.visitInterface(type, callback, contract);
+ }
+ return contract;
+ }
+
+ private <T> Map<String, Operation<Type>> getOperations(Class<T> type, boolean remotable, boolean conversational)
+ throws InvalidServiceContractException {
+ Method[] methods = type.getMethods();
+ Map<String, Operation<Type>> operations = new HashMap<String, Operation<Type>>(methods.length);
+ for (Method method : methods) {
+ String name = method.getName();
+ if (remotable && operations.containsKey(name)) {
+ throw new OverloadedOperationException(method);
+ }
+
+ Type returnType = method.getGenericReturnType();
+ Type[] paramTypes = method.getGenericParameterTypes();
+ Type[] faultTypes = method.getGenericExceptionTypes();
+ boolean nonBlocking = method.isAnnotationPresent(OneWay.class);
+ int conversationSequence = NO_CONVERSATION;
+ if (method.isAnnotationPresent(EndsConversation.class)) {
+ if (!conversational) {
+ throw new InvalidConversationalOperationException(
+ "Method is marked as end conversation but contract is not conversational",
+ method.getDeclaringClass().getName(),
+ method);
+ }
+ conversationSequence = CONVERSATION_END;
+ } else if (conversational) {
+ conversationSequence = Operation.CONVERSATION_CONTINUE;
+ }
+
+ DataType<Type> returnDataType = new DataType<Type>(UNKNOWN_DATABINDING, returnType, returnType);
+ List<DataType<Type>> paramDataTypes = new ArrayList<DataType<Type>>(paramTypes.length);
+ for (Type paramType : paramTypes) {
+ paramDataTypes.add(new DataType<Type>(UNKNOWN_DATABINDING, paramType, paramType));
+ }
+ List<DataType<Type>> faultDataTypes = new ArrayList<DataType<Type>>(faultTypes.length);
+ for (Type faultType : faultTypes) {
+ faultDataTypes.add(new DataType<Type>(UNKNOWN_DATABINDING, faultType, faultType));
+ }
+
+ DataType<List<DataType<Type>>> inputType =
+ new DataType<List<DataType<Type>>>(IDL_INPUT, Object[].class, paramDataTypes);
+ Operation<Type> operation = new Operation<Type>(name,
+ inputType,
+ returnDataType,
+ faultDataTypes,
+ nonBlocking,
+ UNKNOWN_DATABINDING,
+ conversationSequence);
+ operations.put(name, operation);
+ }
+ return operations;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java
new file mode 100644
index 0000000000..3c0986a83e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.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.core.implementation;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessor;
+import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+import org.apache.tuscany.core.util.JavaIntrospectionHelper;
+
+/**
+ * Default implementation of the <code>IntrospectionRegistry</code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class IntrospectionRegistryImpl implements IntrospectionRegistry {
+
+ private Monitor monitor;
+ private List<ImplementationProcessor> cache = new ArrayList<ImplementationProcessor>();
+
+ public IntrospectionRegistryImpl() {
+ }
+
+ public IntrospectionRegistryImpl(Monitor monitor) {
+ this.monitor = monitor;
+ }
+
+ @org.apache.tuscany.api.annotation.Monitor
+ public void setMonitor(Monitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public void registerProcessor(ImplementationProcessor processor) {
+ monitor.register(processor);
+ cache.add(processor);
+ }
+
+ public void unregisterProcessor(ImplementationProcessor processor) {
+ monitor.unregister(processor);
+ cache.remove(processor);
+ }
+
+ public PojoComponentType introspect(Class<?> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitClass(clazz, type, context);
+ }
+
+ for (Constructor<?> constructor : clazz.getConstructors()) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitConstructor(constructor, type, context);
+ }
+ }
+
+ Set<Method> methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz);
+ for (Method method : methods) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitMethod(method, type, context);
+ }
+ }
+
+ Set<Field> fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz);
+ for (Field field : fields) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitField(field, type, context);
+ }
+ }
+
+ Class superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ visitSuperClass(superClass, type, context);
+ }
+
+ for (ImplementationProcessor processor : cache) {
+ processor.visitEnd(clazz, type, context);
+ }
+ return type;
+ }
+
+ private void visitSuperClass(Class<?> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ if (!Object.class.equals(clazz)) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitSuperClass(clazz, type, context);
+ }
+ clazz = clazz.getSuperclass();
+ if (clazz != null) {
+ visitSuperClass(clazz, type, context);
+ }
+ }
+ }
+
+ public static interface Monitor {
+ void register(ImplementationProcessor processor);
+
+ void unregister(ImplementationProcessor processor);
+
+ void processing(ImplementationProcessor processor);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PhysicalComponent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PhysicalComponent.java
new file mode 100644
index 0000000000..0037a2ca38
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PhysicalComponent.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.implementation;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.extension.AbstractComponentExtension;
+import org.apache.tuscany.core.component.scope.InstanceWrapper;
+import org.apache.tuscany.core.component.InstanceFactory;
+
+/**
+ * Base class for implementations of physical components.
+ *
+ * @version $Rev$ $Date$
+ * @param <T> the type of the physical instance
+ */
+public abstract class PhysicalComponent<T> extends AbstractComponentExtension {
+ private final InstanceFactory<T> factory;
+
+ /**
+ * Constructor specifying the component id.
+ *
+ * @param id the component id
+ * @param factory a factory for physical instances
+ */
+ protected PhysicalComponent(URI id, InstanceFactory<T> factory) {
+ super(id);
+ this.factory = factory;
+ }
+
+ public InstanceWrapper<T> createInstance() {
+ return factory.newInstance();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java
new file mode 100644
index 0000000000..e34a8b96c9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java
@@ -0,0 +1,399 @@
+/*
+ * 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.core.implementation;
+
+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.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.ServiceReference;
+import org.osoa.sca.CallableReference;
+
+import org.apache.tuscany.spi.CoreRuntimeException;
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.TargetDestructionException;
+import org.apache.tuscany.spi.component.TargetInitializationException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.extension.AtomicComponentExtension;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.wire.Wire;
+
+import org.apache.tuscany.core.component.ComponentContextImpl;
+import org.apache.tuscany.core.component.ComponentContextProvider;
+import org.apache.tuscany.core.component.ServiceReferenceImpl;
+import org.apache.tuscany.core.injection.ArrayMultiplicityObjectFactory;
+import org.apache.tuscany.core.injection.CallbackWireObjectFactory;
+import org.apache.tuscany.core.injection.ConversationIDObjectFactory;
+import org.apache.tuscany.core.injection.EventInvoker;
+import org.apache.tuscany.core.injection.FieldInjector;
+import org.apache.tuscany.core.injection.Injector;
+import org.apache.tuscany.core.injection.InvalidAccessorException;
+import org.apache.tuscany.core.injection.ListMultiplicityObjectFactory;
+import org.apache.tuscany.core.injection.MethodInjector;
+import org.apache.tuscany.core.injection.NoAccessorException;
+import org.apache.tuscany.core.injection.NoMultiplicityTypeException;
+import org.apache.tuscany.core.injection.ObjectCallbackException;
+import org.apache.tuscany.core.injection.PojoObjectFactory;
+
+/**
+ * Base implementation of an {@link org.apache.tuscany.spi.component.AtomicComponent} whose type is a Java class
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public abstract class PojoAtomicComponent extends AtomicComponentExtension implements ComponentContextProvider {
+ protected EventInvoker<Object> initInvoker;
+ protected EventInvoker<Object> destroyInvoker;
+ protected PojoObjectFactory<?> instanceFactory;
+ protected List<String> constructorParamNames;
+ protected Map<String, Member> referenceSites;
+ protected Map<String, Member> resourceSites;
+ protected Map<String, Member> propertySites;
+ protected Map<String, Member> callbackSites;
+ protected List<Injector<Object>> injectors;
+ protected Class implementationClass;
+ protected Map<String, List<Wire>> wires = new HashMap<String, List<Wire>>();
+ protected Map<String, List<Wire>> callBackwires = new HashMap<String, List<Wire>>();
+
+ private final ComponentContext componentContext;
+ private final Map<String, ObjectFactory<?>> propertyFactories = new ConcurrentHashMap<String, ObjectFactory<?>>();
+ private List<Class<?>> constructorParamTypes = new ArrayList<Class<?>>();
+
+ public PojoAtomicComponent(PojoConfiguration configuration) {
+ super(configuration.getName(),
+ configuration.getProxyService(),
+ configuration.getWorkContext(),
+ configuration.getInitLevel(),
+ configuration.getMaxIdleTime(),
+ configuration.getMaxAge());
+ assert configuration.getInstanceFactory() != null : "Object factory was null";
+ initInvoker = configuration.getInitInvoker();
+ destroyInvoker = configuration.getDestroyInvoker();
+ instanceFactory = configuration.getInstanceFactory();
+ constructorParamNames = configuration.getConstructorParamNames();
+ constructorParamTypes = configuration.getConstructorParamTypes();
+ injectors = new ArrayList<Injector<Object>>();
+ referenceSites = configuration.getReferenceSite() != null ? configuration.getReferenceSite()
+ : new HashMap<String, Member>();
+ propertySites = configuration.getPropertySites() != null ? configuration.getPropertySites()
+ : new HashMap<String, Member>();
+ resourceSites = configuration.getResourceSites() != null ? configuration.getResourceSites()
+ : new HashMap<String, Member>();
+ callbackSites = configuration.getCallbackSites() != null ? configuration.getCallbackSites()
+ : new HashMap<String, Member>();
+ implementationClass = configuration.getImplementationClass();
+
+ componentContext = new ComponentContextImpl(this);
+ }
+
+ public boolean isDestroyable() {
+ return destroyInvoker != null;
+ }
+
+ public void init(Object instance) throws TargetInitializationException {
+ if (initInvoker != null) {
+ try {
+ initInvoker.invokeEvent(instance);
+ } catch (ObjectCallbackException e) {
+ String uri = getUri().toString();
+ throw new TargetInitializationException("Error initializing component instance", uri, e);
+ }
+ }
+ }
+
+ public void destroy(Object instance) throws TargetDestructionException {
+ if (destroyInvoker != null) {
+ try {
+ destroyInvoker.invokeEvent(instance);
+ } catch (ObjectCallbackException e) {
+ throw new TargetDestructionException("Error destroying component instance", getUri().toString(), e);
+ }
+ }
+ }
+
+ public boolean isOptimizable() {
+ // stateless implementations that require a destroy callback cannot be optimized since the callback is
+ // performed by the JavaTargetInvoker
+ return !(getScope() == Scope.STATELESS && isDestroyable());
+ }
+
+ public Object getTargetInstance() throws TargetResolutionException {
+ return scopeContainer.getInstance(this);
+ }
+
+ public Object getAssociatedTargetInstance() throws TargetResolutionException {
+ return scopeContainer.getAssociatedInstance(this);
+ }
+
+ public Object createInstance() throws ObjectCreationException {
+ Object instance = instanceFactory.getInstance();
+ // inject the instance with properties and references
+ for (Injector<Object> injector : injectors) {
+ injector.inject(instance);
+ }
+ return instance;
+ }
+
+ public List<Wire> getWires(String name) {
+ return wires.get(name);
+ }
+
+ public void attachWire(Wire wire) {
+ assert wire.getSourceUri().getFragment() != null;
+ String referenceName = wire.getSourceUri().getFragment();
+ List<Wire> wireList = wires.get(referenceName);
+ if (wireList == null) {
+ wireList = new ArrayList<Wire>();
+ wires.put(referenceName, wireList);
+ }
+ wireList.add(wire);
+ Member member = referenceSites.get(referenceName);
+ if (member != null) {
+ injectors.add(createInjector(member, wire));
+ }
+ // cycle through constructor param names as well
+ for (int i = 0; i < constructorParamNames.size(); i++) {
+ if (referenceName.equals(constructorParamNames.get(i))) {
+ ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories();
+ initializerFactories[i] = createWireFactory(constructorParamTypes.get(i), wire);
+ break;
+ }
+ }
+ //TODO error if ref not set on constructor or ref site
+
+ }
+
+ public void attachWires(List<Wire> attachWires) {
+ assert attachWires.size() > 0;
+ assert attachWires.get(0).getSourceUri().getFragment() != null;
+ String referenceName = attachWires.get(0).getSourceUri().getFragment();
+ List<Wire> wireList = wires.get(referenceName);
+ if (wireList == null) {
+ wireList = new ArrayList<Wire>();
+ wires.put(referenceName, wireList);
+ }
+ wireList.addAll(attachWires);
+ Member member = referenceSites.get(referenceName);
+ if (member == null) {
+ if (constructorParamNames.contains(referenceName)) {
+ // injected on the constructor
+ throw new UnsupportedOperationException();
+ } else {
+ throw new NoAccessorException(referenceName);
+ }
+ }
+
+ Class<?> type = attachWires.get(0).getSourceContract().getInterfaceClass();
+ if (type == null) {
+ throw new NoMultiplicityTypeException("Java interface must be specified for multiplicity", referenceName);
+ }
+ injectors.add(createMultiplicityInjector(member, type, wireList));
+
+ }
+
+ public void attachCallbackWire(Wire wire) {
+ assert wire.getSourceUri().getFragment() != null;
+ String callbackName = wire.getSourceContract().getCallbackName();
+ assert callbackSites.get(callbackName) != null;
+ List<Wire> wireList = callBackwires.get(callbackName);
+ if (wireList == null) {
+ wireList = new ArrayList<Wire>();
+ callBackwires.put(callbackName, wireList);
+ }
+ wireList.add(wire);
+ }
+
+ public void start() throws CoreRuntimeException {
+ if (!callbackSites.isEmpty()) {
+ for (Map.Entry<String, Member> entry : callbackSites.entrySet()) {
+ List<Wire> 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;
+ }
+ Member member = entry.getValue();
+ if (member instanceof Field) {
+ Field field = (Field) member;
+ ObjectFactory<?> factory = new CallbackWireObjectFactory(field.getType(), proxyService, wires);
+ injectors.add(new FieldInjector<Object>(field, factory));
+ } else if (member instanceof Method) {
+ Method method = (Method) member;
+ Class<?> type = method.getParameterTypes()[0];
+ ObjectFactory<?> factory = new CallbackWireObjectFactory(type, proxyService, wires);
+ injectors.add(new MethodInjector<Object>(method, factory));
+ } else {
+ throw new InvalidAccessorException("Member must be a field or method", member.getName());
+ }
+ }
+ }
+ super.start();
+
+ }
+
+ public void addPropertyFactory(String name, ObjectFactory<?> factory) {
+ Member member = propertySites.get(name);
+ if (member instanceof Field) {
+ injectors.add(new FieldInjector<Object>((Field) member, factory));
+ } else if (member instanceof Method) {
+ injectors.add(new MethodInjector<Object>((Method) member, factory));
+ }
+ // cycle through constructor param names as well
+ for (int i = 0; i < constructorParamNames.size(); i++) {
+ if (name.equals(constructorParamNames.get(i))) {
+ ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories();
+ initializerFactories[i] = factory;
+ break;
+ }
+ }
+ //FIXME throw an error if no injection site found
+
+ propertyFactories.put(name, factory);
+ }
+
+ public void addResourceFactory(String name, ObjectFactory<?> factory) {
+ Member member = resourceSites.get(name);
+ if (member instanceof Field) {
+ injectors.add(new FieldInjector<Object>((Field) member, factory));
+ } else if (member instanceof Method) {
+ injectors.add(new MethodInjector<Object>((Method) member, factory));
+ }
+ // cycle through constructor param names as well
+ for (int i = 0; i < constructorParamNames.size(); i++) {
+ if (name.equals(constructorParamNames.get(i))) {
+ ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories();
+ initializerFactories[i] = factory;
+ break;
+ }
+ }
+ //FIXME throw an error if no injection site found
+ }
+
+ public void addConversationIDFactory(Member member) {
+ ObjectFactory<String> convIDObjectFactory = new ConversationIDObjectFactory(workContext);
+ if (member instanceof Field) {
+ injectors.add(new FieldInjector<Object>((Field) member, convIDObjectFactory));
+ } else if (member instanceof Method) {
+ injectors.add(new MethodInjector<Object>((Method) member, convIDObjectFactory));
+ } else {
+ throw new InvalidAccessorException("Member must be a field or method", member.getName());
+ }
+ }
+
+ public boolean implementsCallback(Class callbackClass) {
+ Class<?>[] implementedInterfaces = implementationClass.getInterfaces();
+ for (Class<?> implementedInterface : implementedInterfaces) {
+ if (implementedInterface.isAssignableFrom(callbackClass)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected Injector<Object> createInjector(Member member, Wire wire) {
+ if (member instanceof Field) {
+ Class<?> type = ((Field) member).getType();
+ ObjectFactory<?> factory = createWireFactory(type, wire);
+ return new FieldInjector<Object>((Field) member, factory);
+ } else if (member instanceof Method) {
+ Class<?> type = ((Method) member).getParameterTypes()[0];
+ ObjectFactory<?> factory = createWireFactory(type, wire);
+ return new MethodInjector<Object>((Method) member, factory);
+ } else {
+ throw new InvalidAccessorException("Member must be a field or method", member.getName());
+ }
+ }
+
+ protected Injector<Object> createMultiplicityInjector(Member member,
+ Class<?> interfaceType,
+ List<Wire> wireFactories) {
+ List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>();
+ for (Wire wire : wireFactories) {
+ factories.add(createWireFactory(interfaceType, wire));
+ }
+ if (member instanceof Field) {
+ Field field = (Field) member;
+ if (field.getType().isArray()) {
+ return new FieldInjector<Object>(field, new ArrayMultiplicityObjectFactory(interfaceType, factories));
+ } else {
+ return new FieldInjector<Object>(field, new ListMultiplicityObjectFactory(factories));
+ }
+ } else if (member instanceof Method) {
+ Method method = (Method) member;
+ if (method.getParameterTypes()[0].isArray()) {
+ return new MethodInjector<Object>(method, new ArrayMultiplicityObjectFactory(interfaceType, factories));
+ } else {
+ return new MethodInjector<Object>(method, new ListMultiplicityObjectFactory(factories));
+ }
+ } else {
+ throw new InvalidAccessorException("Member must be a field or method", member.getName());
+ }
+ }
+
+ public ComponentContext getComponentContext() {
+ return componentContext;
+ }
+
+ public <B> B getProperty(Class<B> type, String propertyName) {
+ ObjectFactory<?> factory = propertyFactories.get(propertyName);
+ if (factory != null) {
+ return type.cast(factory.getInstance());
+ } else {
+ return null;
+ }
+
+ }
+
+ public <B> B getService(Class<B> type, String name) {
+ List<Wire> referenceWires = wires.get(name);
+ if (referenceWires == null || referenceWires.size() < 1) {
+ return null;
+ } else {
+ // TODO support multiplicity
+ Wire wire = referenceWires.get(0);
+ ObjectFactory<B> factory = createWireFactory(type, wire);
+ return factory.getInstance();
+ }
+ }
+
+ public <B> ServiceReference<B> getServiceReference(Class<B> type, String name) {
+ List<Wire> referenceWires = wires.get(name);
+ if (referenceWires == null || referenceWires.size() < 1) {
+ return null;
+ } else {
+ // TODO support multiplicity
+ Wire wire = referenceWires.get(0);
+ ObjectFactory<B> factory = createWireFactory(type, wire);
+ return new ServiceReferenceImpl<B>(type, factory);
+ }
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) {
+ return (R) proxyService.cast(target);
+ }
+
+ protected abstract <B> ObjectFactory<B> createWireFactory(Class<B> interfaze, Wire wire);
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoComponentContextFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoComponentContextFactory.java
new file mode 100644
index 0000000000..880802e086
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoComponentContextFactory.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.implementation;
+
+import org.osoa.sca.ComponentContext;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.ObjectCreationException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PojoComponentContextFactory implements ObjectFactory<ComponentContext> {
+ private final PojoAtomicComponent component;
+
+
+ public PojoComponentContextFactory(PojoAtomicComponent component) {
+ this.component = component;
+ }
+
+
+ public ComponentContext getInstance() throws ObjectCreationException {
+ return component.getComponentContext();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java
new file mode 100644
index 0000000000..20676145c8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java
@@ -0,0 +1,203 @@
+/*
+ * 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.core.implementation;
+
+import java.lang.reflect.Member;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.wire.ProxyService;
+
+import org.apache.tuscany.core.injection.EventInvoker;
+import org.apache.tuscany.core.injection.Injector;
+import org.apache.tuscany.core.injection.PojoObjectFactory;
+
+/**
+ * Encapsulates confuration for a Java-based atomic component
+ *
+ * @version $Rev$ $Date$
+ */
+public class PojoConfiguration {
+ private URI name;
+ //private ScopeContainer scopeContainer;
+ private PojoObjectFactory<?> instanceFactory;
+ private List<String> constructorParamNames = new ArrayList<String>();
+ private List<Class<?>> constructorParamTypes = new ArrayList<Class<?>>();
+ private int initLevel;
+ private EventInvoker<Object> initInvoker;
+ private EventInvoker<Object> destroyInvoker;
+ private List<Injector> propertyInjectors = new ArrayList<Injector>();
+ private Map<String, Member> referenceSites = new HashMap<String, Member>();
+ private Map<String, Member> propertySites = new HashMap<String, Member>();
+ private Map<String, Member> resourceSites = new HashMap<String, Member>();
+ private Map<String, Member> callbackSites = new HashMap<String, Member>();
+ private ProxyService proxyService;
+ private WorkContext workContext;
+ private long maxIdleTime = -1;
+ private long maxAge = -1;
+ private Class implementationClass;
+
+ public URI getName() {
+ return name;
+ }
+
+ public void setName(URI name) {
+ this.name = name;
+ }
+
+ public PojoObjectFactory<?> getInstanceFactory() {
+ return instanceFactory;
+ }
+
+ public void setInstanceFactory(PojoObjectFactory<?> objectFactory) {
+ this.instanceFactory = objectFactory;
+ }
+
+ public List<String> getConstructorParamNames() {
+ return constructorParamNames;
+ }
+
+ public void setConstructorParamNames(List<String> names) {
+ constructorParamNames = names;
+ }
+
+ public void addConstructorParamName(String name) {
+ constructorParamNames.add(name);
+ }
+
+ public List<Class<?>> getConstructorParamTypes() {
+ return constructorParamTypes;
+ }
+
+ public void setConstructorParamTypes(List<Class<?>> constructorParamTypes) {
+ this.constructorParamTypes = constructorParamTypes;
+ }
+
+ public void addConstructorParamType(Class<?> type) {
+ constructorParamTypes.add(type);
+ }
+
+ public int getInitLevel() {
+ return initLevel;
+ }
+
+ public void setInitLevel(int initLevel) {
+ this.initLevel = initLevel;
+ }
+
+ public long getMaxIdleTime() {
+ return maxIdleTime;
+ }
+
+ public void setMaxIdleTime(long maxIdleTime) {
+ this.maxIdleTime = maxIdleTime;
+ }
+
+ public long getMaxAge() {
+ return maxAge;
+ }
+
+ public void setMaxAge(long maxAge) {
+ this.maxAge = maxAge;
+ }
+
+ public EventInvoker<Object> getInitInvoker() {
+ return initInvoker;
+ }
+
+ public void setInitInvoker(EventInvoker<Object> initInvoker) {
+ this.initInvoker = initInvoker;
+ }
+
+ public EventInvoker<Object> getDestroyInvoker() {
+ return destroyInvoker;
+ }
+
+ public void setDestroyInvoker(EventInvoker<Object> destroyInvoker) {
+ this.destroyInvoker = destroyInvoker;
+ }
+
+ public List<Injector> getPropertyInjectors() {
+ return propertyInjectors;
+ }
+
+ public void addPropertyInjector(Injector injector) {
+ propertyInjectors.add(injector);
+ }
+
+ public Map<String, Member> getReferenceSite() {
+ return referenceSites;
+ }
+
+ public void addReferenceSite(String name, Member member) {
+ referenceSites.put(name, member);
+ }
+
+ public Map<String, Member> getResourceSites() {
+ return resourceSites;
+ }
+
+ public void addResourceSite(String name, Member member) {
+ resourceSites.put(name, member);
+ }
+
+ public Map<String, Member> getCallbackSites() {
+ return callbackSites;
+ }
+
+ public void addCallbackSite(String name, Member member) {
+ callbackSites.put(name, member);
+ }
+
+ public Map<String, Member> getPropertySites() {
+ return propertySites;
+ }
+
+ public void addPropertySite(String name, Member member) {
+ propertySites.put(name, member);
+ }
+
+ public ProxyService getProxyService() {
+ return proxyService;
+ }
+
+ public void setProxyService(ProxyService proxyService) {
+ this.proxyService = proxyService;
+ }
+
+ public WorkContext getWorkContext() {
+ return workContext;
+ }
+
+ public void setWorkContext(WorkContext workContext) {
+ this.workContext = workContext;
+ }
+
+ public Class getImplementationClass() {
+ return implementationClass;
+ }
+
+ public void setImplementationClass(Class implementationClass) {
+ this.implementationClass = implementationClass;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java
new file mode 100644
index 0000000000..d12b407ea7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core.implementation.composite;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.BuilderInstantiationException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentBuilderExtension;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * Abstract builder for composites
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractCompositeBuilder<T extends Implementation<CompositeComponentType>>
+ extends ComponentBuilderExtension<T> {
+
+ public Component build(
+ Component component,
+ CompositeComponentType<?, ?, ?> componentType,
+ DeploymentContext deploymentContext) throws BuilderException {
+ for (ComponentDefinition<? extends Implementation<?>> definition : componentType.getComponents().values()) {
+ builderRegistry.build(definition, deploymentContext);
+ }
+ for (ServiceDefinition definition : componentType.getServices().values()) {
+ try {
+ Service service = builderRegistry.build(definition, deploymentContext);
+ component.register(service);
+ } catch (RegistrationException e) {
+ throw new BuilderInstantiationException("Error registering service", e);
+ }
+ }
+ for (ReferenceDefinition definition : componentType.getReferences().values()) {
+ try {
+ Reference reference = builderRegistry.build(definition, deploymentContext);
+ component.register(reference);
+ } catch (RegistrationException e) {
+ throw new BuilderInstantiationException("Error registering reference", e);
+ }
+ }
+ return component;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java
new file mode 100644
index 0000000000..ed64cb1236
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.core.implementation.composite;
+
+import org.apache.tuscany.spi.component.ComponentRuntimeException;
+
+/**
+ * Denotes a condition where a component times out waiting to perform an operation
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentTimeoutException extends ComponentRuntimeException {
+
+ public ComponentTimeoutException(String message) {
+ super(message);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java
new file mode 100644
index 0000000000..51d360ec39
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java
@@ -0,0 +1,51 @@
+/*
+ * 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.core.implementation.composite;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.CompositeImplementation;
+
+/**
+ * Instantiates a composite component from an assembly definition
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeBuilder extends AbstractCompositeBuilder<CompositeImplementation> {
+
+ public Component build(ComponentDefinition<CompositeImplementation> componentDefinition,
+ DeploymentContext deploymentContext) throws BuilderException {
+
+ CompositeImplementation implementation = componentDefinition.getImplementation();
+ CompositeComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ URI name = componentDefinition.getUri();
+ CompositeComponentImpl component = new CompositeComponentImpl(name);
+
+ return build(component, componentType, deploymentContext);
+ }
+
+ protected Class<CompositeImplementation> getImplementationType() {
+ return CompositeImplementation.class;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java
new file mode 100644
index 0000000000..8df05048c8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java
@@ -0,0 +1,121 @@
+/*
+ * 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.core.implementation.composite;
+
+import java.net.URI;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.extension.CompositeComponentExtension;
+import org.apache.tuscany.spi.wire.Wire;
+
+import org.apache.tuscany.core.component.event.ComponentStop;
+
+/**
+ * The standard implementation of a composite component. Autowiring is performed by delegating to the parent composite.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeComponentImpl extends CompositeComponentExtension {
+ public static final int DEFAULT_WAIT = 1000 * 60;
+ // Blocking latch to ensure the composite is initialized exactly once prior to servicing requests
+ protected CountDownLatch initializeLatch = new CountDownLatch(1);
+ protected final Object lock = new Object();
+ // Indicates whether the composite context has been initialized
+ protected boolean initialized;
+
+ /**
+ * Constructor
+ *
+ * @param name the name of this Component
+ */
+ public CompositeComponentImpl(URI name) {
+ super(name);
+ }
+
+ public void attachWire(Wire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void attachWires(List<Wire> wires) {
+ throw new UnsupportedOperationException();
+ }
+
+ public List<Wire> getWires(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void attachCallbackWire(Wire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void start() {
+ synchronized (lock) {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Composite not in UNINITIALIZED state");
+ }
+ initializeLatch.countDown();
+ initialized = true;
+ lifecycleState = INITIALIZED;
+ }
+ }
+
+ public void stop() {
+ if (lifecycleState == STOPPED) {
+ return;
+ }
+
+ publish(new ComponentStop(this, getUri()));
+ // need to block a start until reset is complete
+ initializeLatch = new CountDownLatch(2);
+ lifecycleState = STOPPING;
+ initialized = false;
+ // allow initialized to be called
+ initializeLatch.countDown();
+ lifecycleState = STOPPED;
+ }
+
+ public void publish(Event event) {
+ if (lifecycleState == STOPPED) {
+ return;
+ }
+ checkInit();
+ super.publish(event);
+ }
+
+ /**
+ * Blocks until the composite context has been initialized
+ */
+ protected void checkInit() throws ComponentTimeoutException {
+ if (!initialized) {
+ try {
+ /* block until the composite has initialized */
+ boolean success = initializeLatch.await(DEFAULT_WAIT, TimeUnit.MILLISECONDS);
+ if (!success) {
+ throw new ComponentTimeoutException("Timeout waiting for context to initialize");
+ }
+ } catch (InterruptedException e) { // should not happen
+ }
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java
new file mode 100644
index 0000000000..61942fc66f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.composite;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.spi.deployer.CompositeClassLoader;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.CompositeImplementation;
+
+import org.apache.tuscany.core.deployer.ChildDeploymentContext;
+
+/**
+ * Loads a composite component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeComponentTypeLoader extends ComponentTypeLoaderExtension<CompositeImplementation> {
+ public CompositeComponentTypeLoader() {
+ }
+
+ public CompositeComponentTypeLoader(LoaderRegistry loaderRegistry) {
+ super(loaderRegistry);
+ }
+
+ protected Class<CompositeImplementation> getImplementationClass() {
+ return CompositeImplementation.class;
+ }
+
+ public void load(CompositeImplementation implementation, DeploymentContext context) throws LoaderException {
+ URL scdlLocation = implementation.getScdlLocation();
+ ClassLoader cl = new CompositeClassLoader(implementation.getClassLoader());
+ URI componentId = URI.create(context.getComponentId().toString() + '/');
+ DeploymentContext childContext =
+ new ChildDeploymentContext(context, cl, scdlLocation, componentId, context.isAutowire());
+ CompositeComponentType componentType = loadFromSidefile(scdlLocation, childContext);
+ implementation.setComponentType(componentType);
+ }
+
+ protected CompositeComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext)
+ throws LoaderException {
+ return loaderRegistry.load(null, url, CompositeComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java
new file mode 100644
index 0000000000..af0a5a7a56
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java
@@ -0,0 +1,251 @@
+/*
+ * 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.core.implementation.composite;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.CompositeClassLoader;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidServiceException;
+import org.apache.tuscany.spi.loader.InvalidWireException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.Include;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ReferenceTarget;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.apache.tuscany.spi.model.WireDefinition;
+import org.apache.tuscany.spi.services.artifact.Artifact;
+import org.apache.tuscany.spi.services.artifact.ArtifactRepository;
+
+import org.apache.tuscany.core.property.PropertyHelper;
+
+/**
+ * Loads a composite component definition from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeLoader extends LoaderExtension<CompositeComponentType> {
+ public static final QName COMPOSITE = new QName(SCA_NS, "composite");
+ public static final String URI_DELIMITER = "/";
+
+ private final ArtifactRepository artifactRepository;
+
+ public CompositeLoader(@Reference LoaderRegistry registry, @Reference ArtifactRepository artifactRepository) {
+ super(registry);
+ this.artifactRepository = artifactRepository;
+ }
+
+ public QName getXMLType() {
+ return COMPOSITE;
+ }
+
+ public CompositeComponentType load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+
+ String name = reader.getAttributeValue(null, "name");
+ String targetNamespace = reader.getAttributeValue(null, "targetNamespace");
+ boolean autowire = Boolean.parseBoolean(reader.getAttributeValue(null, "autowire"));
+
+ CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> type =
+ new CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>(
+ new QName(targetNamespace, name)
+ );
+ type.setAutowire(autowire);
+ boolean done = false;
+ while (!done) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ boolean oldAutowire = deploymentContext.isAutowire();
+ deploymentContext.setAutowire(autowire);
+ ModelObject o = registry.load(type, reader, deploymentContext);
+ deploymentContext.setAutowire(oldAutowire);
+ if (o instanceof ServiceDefinition) {
+ type.add((ServiceDefinition) o);
+ } else if (o instanceof ReferenceDefinition) {
+ type.add((ReferenceDefinition) o);
+ } else if (o instanceof Property<?>) {
+ type.add((Property<?>) o);
+ } else if (o instanceof ComponentDefinition<?>) {
+ type.add((ComponentDefinition<?>) o);
+ } else if (o instanceof Include) {
+ type.add((Include) o);
+ } else if (o instanceof Dependency) {
+ Artifact artifact = ((Dependency) o).getArtifact();
+ if (artifactRepository == null) {
+ throw new MissingResourceException("No ArtifactRepository configured for this system",
+ artifact.toString()
+ );
+ }
+
+ // default to jar type if not specified
+ if (artifact.getType() == null) {
+ artifact.setType("jar");
+ }
+ artifactRepository.resolve(artifact);
+ if (artifact.getUrl() == null) {
+ throw new MissingResourceException("Dependency not found", artifact.toString());
+ }
+
+ ClassLoader classLoader = deploymentContext.getClassLoader();
+ if (classLoader instanceof CompositeClassLoader) {
+ CompositeClassLoader ccl = (CompositeClassLoader) classLoader;
+ for (URL dep : artifact.getUrls()) {
+ ccl.addURL(dep);
+ }
+ }
+ } else if (o instanceof WireDefinition) {
+ type.add((WireDefinition) o);
+ } else {
+ // add as an unknown model extension
+ if (o != null) {
+ type.getExtensions().put(o.getClass(), o);
+ }
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (COMPOSITE.equals(reader.getName())) {
+ // if there are wire defintions then link them up to the relevant components
+ resolveWires(type);
+ verifyCompositeCompleteness(type);
+ done = true;
+ break;
+ }
+ }
+ }
+ for (ComponentDefinition<? extends Implementation<?>> c : type.getComponents().values()) {
+ PropertyHelper.processProperties(type, c, deploymentContext);
+ }
+ return type;
+ }
+
+ protected void resolveWires(CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite)
+ throws InvalidWireException {
+ ComponentDefinition componentDefinition;
+ ServiceDefinition serviceDefinition;
+ List<WireDefinition> wireDefns = composite.getDeclaredWires();
+ for (WireDefinition wire : wireDefns) {
+ URI targetUri = wire.getTarget();
+ // validate the target before finding the source
+ validateTarget(targetUri, composite);
+
+ String sourceName = wire.getSource().getPath(); //new QualifiedName(wire.getSource().getPath());
+ serviceDefinition = composite.getDeclaredServices().get(sourceName);
+ if (serviceDefinition != null) {
+ serviceDefinition.setTarget(wire.getTarget());
+ } else {
+ componentDefinition = composite.getDeclaredComponents().get(sourceName);
+ if (componentDefinition != null) {
+ if (wire.getSource().getFragment() == null) {
+ throw new InvalidWireException("Source reference not specified", sourceName);
+ }
+ URI referenceName = URI.create(wire.getSource().getFragment());
+ ReferenceTarget referenceTarget = createReferenceTarget(referenceName,
+ targetUri,
+ componentDefinition);
+ componentDefinition.add(referenceTarget);
+ } else {
+ throw new InvalidWireException("Source not found", sourceName);
+ }
+ }
+ }
+ }
+
+ private ReferenceTarget createReferenceTarget(URI componentReferenceName,
+ URI target,
+ ComponentDefinition componentDefn) throws InvalidWireException {
+ ComponentType componentType = componentDefn.getImplementation().getComponentType();
+ if (componentReferenceName == null) {
+ // if there is ambiguity in determining the source of the wire or there is no reference to be wired
+ if (componentType.getReferences().size() > 1 || componentType.getReferences().isEmpty()) {
+ throw new InvalidWireException("Unable to determine unique source reference");
+ } else {
+ Map references = componentType.getReferences();
+ ReferenceDefinition definition = (ReferenceDefinition) references.values().iterator().next();
+ componentReferenceName = definition.getUri();
+ }
+ }
+
+ ReferenceTarget referenceTarget = new ReferenceTarget();
+ referenceTarget.setReferenceName(componentReferenceName);
+ referenceTarget.addTarget(target);
+ return referenceTarget;
+ }
+
+ protected void verifyCompositeCompleteness(
+ CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite)
+ throws InvalidServiceException {
+ // check if all of the composite services have been wired
+ for (ServiceDefinition svcDefn : composite.getDeclaredServices().values()) {
+ if (svcDefn.getTarget() == null) {
+ String identifier = svcDefn.getUri().toString();
+ throw new InvalidServiceException("Composite service not wired to a target", identifier);
+ }
+ }
+ }
+
+ private void validateTarget(URI target,
+ CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite)
+ throws InvalidWireException {
+ // if target is not a reference of the composite
+ String targetName = target.getPath();
+ if (composite.getReferences().get(targetName) == null) {
+ ComponentDefinition<?> targetDefinition = composite.getDeclaredComponents().get(targetName);
+ // if a target component exists in this composite
+ if (targetDefinition != null) {
+ Implementation<?> implementation = targetDefinition.getImplementation();
+ ComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ Map<String, ? extends ServiceDefinition> services = componentType.getServices();
+ if (target.getFragment() == null) {
+ if (services.size() > 1 || services.isEmpty()) {
+ throw new InvalidWireException("Ambiguous target", target.toString());
+ }
+ } else {
+ if (services.get(target.getFragment()) == null) {
+ throw new InvalidWireException("Invalid target service", target.toString());
+ }
+ }
+ } else {
+ throw new InvalidWireException("Target not found", target.toString());
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java
new file mode 100644
index 0000000000..808f36072f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.implementation.composite;
+
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.services.artifact.Artifact;
+
+/**
+ * A model object that represents a dependency on an external artifact.
+ *
+ * @version $Rev$ $Date$
+ */
+public class Dependency extends ModelObject {
+ private Artifact artifact;
+
+ public Artifact getArtifact() {
+ return artifact;
+ }
+
+ public void setArtifact(Artifact artifact) {
+ this.artifact = artifact;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java
new file mode 100644
index 0000000000..48836cd62f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java
@@ -0,0 +1,125 @@
+/*
+ * 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.core.implementation.composite;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Set;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.Constants;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.CompositeClassLoader;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidValueException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+import org.apache.tuscany.spi.model.CompositeImplementation;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.services.artifact.Artifact;
+import org.apache.tuscany.spi.services.artifact.ArtifactRepository;
+
+/**
+ * Loader that handles an &lt;implementation.composite&gt; element.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ImplementationCompositeLoader extends LoaderExtension<CompositeImplementation> {
+ private static final QName IMPLEMENTATION_COMPOSITE =
+ new QName(Constants.SCA_NS, "implementation.composite");
+
+ private final ArtifactRepository artifactRepository;
+
+ public ImplementationCompositeLoader(@Reference LoaderRegistry registry,
+ @Reference ArtifactRepository artifactRepository) {
+ super(registry);
+ this.artifactRepository = artifactRepository;
+ }
+
+ public QName getXMLType() {
+ return IMPLEMENTATION_COMPOSITE;
+ }
+
+ public CompositeImplementation load(
+ ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ assert IMPLEMENTATION_COMPOSITE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String group = reader.getAttributeValue(null, "group");
+ String version = reader.getAttributeValue(null, "version");
+ String scdlLocation = reader.getAttributeValue(null, "scdlLocation");
+ String jarLocation = reader.getAttributeValue(null, "jarLocation");
+ LoaderUtil.skipToEndElement(reader);
+
+ CompositeImplementation impl = new CompositeImplementation();
+ impl.setName(name);
+ if (scdlLocation != null) {
+ try {
+ impl.setScdlLocation(new URL(deploymentContext.getScdlLocation(), scdlLocation));
+ } catch (MalformedURLException e) {
+ throw new InvalidValueException(scdlLocation, name, e);
+ }
+ impl.setClassLoader(deploymentContext.getClassLoader());
+ } else if (jarLocation != null) {
+ URL jarUrl;
+ try {
+ jarUrl = new URL(deploymentContext.getScdlLocation(), jarLocation);
+ } catch (MalformedURLException e) {
+ throw new InvalidValueException(jarLocation, name, e);
+ }
+ try {
+ impl.setScdlLocation(new URL("jar:" + jarUrl.toExternalForm() + "!/META-INF/sca/default.scdl"));
+ } catch (MalformedURLException e) {
+ throw new AssertionError("Could not convert URL to a jar: url");
+ }
+ impl.setClassLoader(new CompositeClassLoader(new URL[]{jarUrl}, deploymentContext.getClassLoader()));
+ } else if (artifactRepository != null && group != null && version != null) {
+ Artifact artifact = new Artifact();
+ artifact.setGroup(group);
+ artifact.setName(name);
+ artifact.setVersion(version);
+ artifact.setType("jar");
+ artifactRepository.resolve(artifact);
+ if (artifact.getUrl() == null) {
+ throw new MissingResourceException(artifact.toString(), name);
+ }
+ try {
+ impl.setScdlLocation(new URL("jar:" + artifact.getUrl() + "!/META-INF/sca/default.scdl"));
+ } catch (MalformedURLException e) {
+ throw new AssertionError(e);
+ }
+ Set<URL> artifactURLs = artifact.getUrls();
+ URL[] urls = new URL[artifactURLs.size()];
+ int i = 0;
+ for (URL artifactURL : artifactURLs) {
+ urls[i++] = artifactURL;
+ }
+ impl.setClassLoader(new CompositeClassLoader(urls, deploymentContext.getClassLoader()));
+ }
+ return impl;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java
new file mode 100644
index 0000000000..f2a8109ee3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java
@@ -0,0 +1,58 @@
+/*
+ * 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.core.implementation.composite;
+
+import javax.security.auth.Subject;
+
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.ServiceReference;
+import org.osoa.sca.CallableReference;
+
+import org.apache.tuscany.spi.component.WorkContext;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ManagedRequestContext implements RequestContext {
+ private WorkContext workContext;
+
+ public ManagedRequestContext(WorkContext workContext) {
+ this.workContext = workContext;
+ }
+
+ public Subject getSecuritySubject() {
+ throw new UnsupportedOperationException();
+ }
+
+ public String getServiceName() {
+ return workContext.getCurrentServiceName();
+ }
+
+ public <B> ServiceReference<B> getServiceReference() {
+ throw new UnsupportedOperationException();
+ }
+
+ public <CB> CB getCallback() {
+ throw new UnsupportedOperationException();
+ }
+
+ public <CB> CallableReference<CB> getCallbackReference() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java
new file mode 100644
index 0000000000..f824980f29
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java
@@ -0,0 +1,71 @@
+/*
+ * 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.core.implementation.composite;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tuscany.spi.component.AbstractSCAObject;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+/**
+ * The default implementation of a {@link org.apache.tuscany.spi.component.Reference}
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReferenceImpl extends AbstractSCAObject implements Reference {
+ private ServiceContract<?> serviceContract;
+ private List<ReferenceBinding> bindings = new ArrayList<ReferenceBinding>();
+
+ public ReferenceImpl(URI name, ServiceContract<?> contract) {
+ super(name);
+ this.serviceContract = contract;
+ }
+
+ public ServiceContract<?> getServiceContract() {
+ return serviceContract;
+ }
+
+ public List<ReferenceBinding> getReferenceBindings() {
+ return Collections.unmodifiableList(bindings);
+ }
+
+ public void addReferenceBinding(ReferenceBinding binding) {
+ bindings.add(binding);
+ }
+
+ public void start() {
+ super.start();
+ for (ReferenceBinding binding : bindings) {
+ binding.start();
+ }
+ }
+
+ public void stop() {
+ super.stop();
+ for (ReferenceBinding binding : bindings) {
+ binding.stop();
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java
new file mode 100644
index 0000000000..b8b9b00b49
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java
@@ -0,0 +1,81 @@
+/*
+ * 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.core.implementation.composite;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tuscany.spi.component.AbstractSCAObject;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.component.ServiceBinding;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+/**
+ * The default implementation of a {@link Service}
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceImpl extends AbstractSCAObject implements Service {
+ private ServiceContract<?> serviceContract;
+ private List<ServiceBinding> bindings = new ArrayList<ServiceBinding>();
+ private URI targetUri;
+
+ public ServiceImpl(URI name, ServiceContract<?> contract) {
+ this(name, contract, null);
+ }
+
+ public ServiceImpl(URI name, ServiceContract<?> contract, URI targetUri) {
+ super(name);
+ this.serviceContract = contract;
+ this.targetUri = targetUri;
+ }
+
+ public ServiceContract<?> getServiceContract() {
+ return serviceContract;
+ }
+
+ public URI getTargetUri() {
+ return targetUri;
+ }
+
+ public List<ServiceBinding> getServiceBindings() {
+ return Collections.unmodifiableList(bindings);
+ }
+
+ public void addServiceBinding(ServiceBinding binding) {
+ bindings.add(binding);
+ }
+
+ public void start() {
+ super.start();
+ for (ServiceBinding binding : bindings) {
+ binding.start();
+ }
+ }
+
+ public void stop() {
+ super.stop();
+ for (ServiceBinding binding : bindings) {
+ binding.stop();
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java
new file mode 100644
index 0000000000..531f610bf9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.composite;
+
+import java.net.URI;
+
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.BuilderRegistry;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+
+/**
+ * Produces system composite components by evaluating an assembly.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemCompositeBuilder extends AbstractCompositeBuilder<SystemCompositeImplementation> {
+
+ @Constructor
+ public SystemCompositeBuilder(@Reference BuilderRegistry builderRegistry) {
+ this.builderRegistry = builderRegistry;
+ }
+
+ public Component build(ComponentDefinition<SystemCompositeImplementation> componentDefinition,
+ DeploymentContext context) throws BuilderException {
+ SystemCompositeImplementation impl = componentDefinition.getImplementation();
+ CompositeComponentType<?, ?, ?> componentType = impl.getComponentType();
+ URI name = componentDefinition.getUri();
+ Component component = new CompositeComponentImpl(name);
+ build(component, componentType, context);
+ return component;
+ }
+
+ protected Class<SystemCompositeImplementation> getImplementationType() {
+ return SystemCompositeImplementation.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java
new file mode 100644
index 0000000000..3ecae61a46
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java
@@ -0,0 +1,66 @@
+/*
+ * 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.core.implementation.java;
+
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+import org.apache.tuscany.core.implementation.PojoAtomicComponent;
+import org.apache.tuscany.core.implementation.PojoConfiguration;
+import org.apache.tuscany.core.wire.WireObjectFactory;
+
+/**
+ * The runtime instantiation of Java component implementations
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaAtomicComponent extends PojoAtomicComponent {
+
+ public JavaAtomicComponent(PojoConfiguration configuration) {
+ super(configuration);
+ }
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation)
+ throws TargetInvokerCreationException {
+ Method[] methods;
+ Class callbackClass = null;
+ if (operation.isCallback()) {
+ callbackClass = operation.getServiceContract().getCallbackClass();
+ methods = callbackClass.getMethods();
+
+ } else {
+ methods = implementationClass.getMethods();
+ }
+ Method method = findMethod(operation, methods);
+ if (method == null) {
+ throw new TargetMethodNotFoundException(operation);
+ }
+ return new JavaTargetInvoker(method, this, callbackClass, workContext);
+ }
+
+ protected <B> ObjectFactory<B> createWireFactory(Class<B> interfaze, Wire wire) {
+ return new WireObjectFactory<B>(interfaze, wire, proxyService);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponent.java
new file mode 100644
index 0000000000..4ab2cfd9ce
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponent.java
@@ -0,0 +1,163 @@
+/*
+ * 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.core.implementation.java;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.core.component.InstanceFactory;
+import org.apache.tuscany.spi.CoreRuntimeException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.event.EventFilter;
+import org.apache.tuscany.spi.event.RuntimeEventListener;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.PropertyValue;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+import org.osoa.sca.ComponentContext;
+
+/**
+ *
+ * @version $Revision$ $Date$
+ *
+ */
+public class JavaComponent implements Component {
+
+ // Instance factory class
+ private Class<InstanceFactory<?>> instanceFactoryClass; //NOPMD
+
+ // Scope container
+ private ScopeContainer scopeContainer; //NOPMD
+
+ /**
+ * Injects the instance factory class.
+ * @param instanceFactoryClass Instance factory class.
+ */
+ public void setInstanceFactoryClass(Class<InstanceFactory<?>> instanceFactoryClass) {
+ this.instanceFactoryClass = instanceFactoryClass;
+ }
+
+ /**
+ * Injects the scope container.
+ * @param scopeContainer Scope container.
+ */
+ public void setScopeContainer(ScopeContainer scopeContainer) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ public void attachCallbackWire(Wire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void attachWire(Wire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void attachWires(List<Wire> wires) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ComponentContext getComponentContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map<String, PropertyValue<?>> getDefaultPropertyValues() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Reference getReference(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Scope getScope() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Service getService(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public List<Wire> getWires(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isOptimizable() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void register(Service service) throws RegistrationException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void register(Reference reference) throws RegistrationException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setDefaultPropertyValues(Map<String, PropertyValue<?>> defaultPropertyValues) {
+ throw new UnsupportedOperationException();
+ }
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation)
+ throws TargetInvokerCreationException {
+ throw new UnsupportedOperationException();
+ }
+
+ public URI getUri() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addListener(RuntimeEventListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addListener(EventFilter filter, RuntimeEventListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void publish(Event object) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeListener(RuntimeEventListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getLifecycleState() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void start() throws CoreRuntimeException {
+ throw new UnsupportedOperationException();
+ }
+
+ public void stop() throws CoreRuntimeException {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java
new file mode 100644
index 0000000000..7f2fdd7627
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java
@@ -0,0 +1,195 @@
+/*
+ * 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.core.implementation.java;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.builder.BuilderConfigException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentBuilderExtension;
+import org.apache.tuscany.spi.host.ResourceHost;
+import org.apache.tuscany.spi.implementation.java.ConstructorDefinition;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.Resource;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.PropertyValue;
+
+import org.apache.tuscany.core.implementation.PojoComponentContextFactory;
+import org.apache.tuscany.core.implementation.PojoConfiguration;
+import org.apache.tuscany.core.injection.MethodEventInvoker;
+import org.apache.tuscany.core.injection.PojoObjectFactory;
+import org.apache.tuscany.core.injection.ResourceObjectFactory;
+
+/**
+ * Builds a Java-based atomic context from a component definition
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class JavaComponentBuilder extends ComponentBuilderExtension<JavaImplementation> {
+
+ private ResourceHost host;
+
+ @Reference
+ public void setHost(ResourceHost host) {
+ this.host = host;
+ }
+
+ @SuppressWarnings("unchecked")
+ public AtomicComponent build(ComponentDefinition<JavaImplementation> definition, DeploymentContext context)
+ throws BuilderConfigException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ definition.getImplementation().getComponentType();
+
+ PojoConfiguration configuration = new PojoConfiguration();
+ if (definition.getInitLevel() != null) {
+ configuration.setInitLevel(definition.getInitLevel());
+ } else {
+ configuration.setInitLevel(componentType.getInitLevel());
+ }
+ if (componentType.getMaxAge() > 0) {
+ configuration.setMaxAge(componentType.getMaxAge());
+ } else if (componentType.getMaxIdleTime() > 0) {
+ configuration.setMaxIdleTime(componentType.getMaxIdleTime());
+ }
+ Method initMethod = componentType.getInitMethod();
+ if (initMethod != null) {
+ configuration.setInitInvoker(new MethodEventInvoker(initMethod));
+ }
+ Method destroyMethod = componentType.getDestroyMethod();
+ if (destroyMethod != null) {
+ configuration.setDestroyInvoker(new MethodEventInvoker(destroyMethod));
+ }
+
+ configuration.setProxyService(proxyService);
+ configuration.setWorkContext(workContext);
+ configuration.setImplementationClass(definition.getImplementation().getImplementationClass());
+
+ // setup property injection sites
+ for (JavaMappedProperty<?> property : componentType.getProperties().values()) {
+ configuration.addPropertySite(property.getName(), property.getMember());
+ }
+
+ // setup reference injection sites
+ for (JavaMappedReference reference : componentType.getReferences().values()) {
+ Member member = reference.getMember();
+ if (member != null) {
+ // could be null if the reference is mapped to a constructor
+ configuration.addReferenceSite(reference.getUri().getFragment(), member);
+ }
+ }
+
+ for (Resource resource : componentType.getResources().values()) {
+ Member member = resource.getMember();
+ if (member != null) {
+ // could be null if the resource is mapped to a constructor
+ configuration.addResourceSite(resource.getName(), member);
+ }
+ }
+
+ // setup constructor injection
+ ConstructorDefinition<?> ctorDef = componentType.getConstructorDefinition();
+ Constructor<?> constr = ctorDef.getConstructor();
+ PojoObjectFactory<?> instanceFactory = new PojoObjectFactory(constr);
+ configuration.setInstanceFactory(instanceFactory);
+ configuration.getConstructorParamNames().addAll(ctorDef.getInjectionNames());
+ for (Class<?> clazz : constr.getParameterTypes()) {
+ configuration.addConstructorParamType(clazz);
+ }
+ configuration.setName(definition.getUri());
+ handleCallbackSites(componentType, configuration);
+
+ JavaAtomicComponent component = new JavaAtomicComponent(configuration);
+
+ // handle properties
+ handleProperties(definition, component);
+
+ // handle resources
+ handleResources(componentType, component);
+
+ if (componentType.getConversationIDMember() != null) {
+ component.addConversationIDFactory(componentType.getConversationIDMember());
+ }
+
+ return component;
+ }
+
+ private void handleCallbackSites(
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType,
+ PojoConfiguration configuration) {
+ for (JavaMappedService service : componentType.getServices().values()) {
+ // setup callback injection sites
+ String name = service.getServiceContract().getCallbackName();
+ if (name != null) {
+ // Only if there is a callback reference in the service
+ configuration.addCallbackSite(name, service.getCallbackMember());
+ }
+ }
+ }
+
+ private void handleResources(
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType,
+ JavaAtomicComponent component) {
+ for (Resource<?> resource : componentType.getResources().values()) {
+ String name = resource.getName();
+ ObjectFactory<?> objectFactory = resource.getObjectFactory();
+ if (objectFactory == null) {
+ Class<?> type = resource.getType();
+ if (ComponentContext.class.equals(type)) {
+ objectFactory = new PojoComponentContextFactory(component);
+ } else {
+ boolean optional = resource.isOptional();
+ String mappedName = resource.getMappedName();
+ objectFactory = createResourceObjectFactory(type, mappedName, optional, host);
+ }
+ }
+ component.addResourceFactory(name, objectFactory);
+ }
+ }
+
+ private <T> ResourceObjectFactory<T> createResourceObjectFactory(Class<T> type,
+ String mappedName,
+ boolean optional,
+ ResourceHost host) {
+ return new ResourceObjectFactory<T>(type, mappedName, optional, host);
+ }
+
+ private void handleProperties(ComponentDefinition<JavaImplementation> definition, JavaAtomicComponent component) {
+ for (PropertyValue<?> property : definition.getPropertyValues().values()) {
+ ObjectFactory<?> factory = property.getValueFactory();
+ if (factory != null) {
+ component.addPropertyFactory(property.getName(), factory);
+ }
+ }
+ }
+
+ protected Class<JavaImplementation> getImplementationType() {
+ return JavaImplementation.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java
new file mode 100644
index 0000000000..c4234596f8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java
@@ -0,0 +1,86 @@
+/*
+ * 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.core.implementation.java;
+
+import java.net.URL;
+
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension;
+import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry;
+import org.apache.tuscany.spi.implementation.java.Introspector;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+
+import org.apache.tuscany.core.util.JavaIntrospectionHelper;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JavaComponentTypeLoader extends ComponentTypeLoaderExtension<JavaImplementation> {
+ private Introspector introspector;
+
+ @Constructor({"registry", "introspector"})
+ public JavaComponentTypeLoader(@Reference LoaderRegistry loaderRegistry,
+ @Reference IntrospectionRegistry introspector) {
+ super(loaderRegistry);
+ this.introspector = introspector;
+ }
+
+ @Override
+ protected Class<JavaImplementation> getImplementationClass() {
+ return JavaImplementation.class;
+ }
+
+ public void load(
+ JavaImplementation implementation,
+ DeploymentContext deploymentContext) throws LoaderException {
+ Class<?> implClass = implementation.getImplementationClass();
+ URL resource = implClass.getResource(JavaIntrospectionHelper.getBaseName(implClass) + ".componentType");
+ PojoComponentType componentType;
+ if (resource == null) {
+ componentType = loadByIntrospection(implementation, deploymentContext);
+ } else {
+ componentType = loadFromSidefile(resource, deploymentContext);
+ }
+ implementation.setComponentType(componentType);
+ }
+
+ protected PojoComponentType loadByIntrospection(JavaImplementation implementation, DeploymentContext context)
+ throws ProcessingException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>();
+ Class<?> implClass = implementation.getImplementationClass();
+ introspector.introspect(implClass, componentType, context);
+ return componentType;
+ }
+
+ protected PojoComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>();
+ return loaderRegistry.load(componentType, url, PojoComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java
new file mode 100644
index 0000000000..432bf31d63
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java
@@ -0,0 +1,62 @@
+/*
+ * 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.core.implementation.java;
+
+import org.apache.tuscany.spi.model.AtomicImplementation;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+
+/**
+ * @version $$Rev$$ $$Date$$
+ */
+public class JavaImplementation extends AtomicImplementation<PojoComponentType> {
+ private String className;
+ private Class<?> implementationClass;
+
+ public JavaImplementation() {
+ }
+
+ public JavaImplementation(Class<?> implementationClass) {
+ this.implementationClass = implementationClass;
+ this.className = implementationClass.getName();
+ }
+
+ public JavaImplementation(Class<?> implementationClass, PojoComponentType componentType) {
+ super(componentType);
+ this.implementationClass = implementationClass;
+ this.className = implementationClass == null ? null : implementationClass.getName();
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public void setClassName(String className) {
+ this.className = className;
+ this.implementationClass = null;
+ }
+
+ public Class<?> getImplementationClass() {
+ return implementationClass;
+ }
+
+ public void setImplementationClass(Class<?> implementationClass) {
+ this.implementationClass = implementationClass;
+ this.className = implementationClass.getName();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java
new file mode 100644
index 0000000000..91f3852c0e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.java;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.model.ModelObject;
+
+public class JavaImplementationLoader extends LoaderExtension {
+ public static final QName IMPLEMENTATION_JAVA = new QName(SCA_NS, "implementation.java");
+
+ @Constructor
+ public JavaImplementationLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public QName getXMLType() {
+ return IMPLEMENTATION_JAVA;
+ }
+
+ public ModelObject load(ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+ assert IMPLEMENTATION_JAVA.equals(reader.getName());
+ String implClass = reader.getAttributeValue(null, "class");
+ Class<?> implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader());
+
+ JavaImplementation implementation = new JavaImplementation();
+ implementation.setClassName(implClass);
+ implementation.setImplementationClass(implementationClass);
+ registry.loadComponentType(implementation, deploymentContext);
+ LoaderUtil.skipToEndElement(reader);
+ return implementation;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaPhysicalComponentBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaPhysicalComponentBuilder.java
new file mode 100644
index 0000000000..7758aa69d3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaPhysicalComponentBuilder.java
@@ -0,0 +1,108 @@
+/*
+ * 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.core.implementation.java;
+
+import java.net.URI;
+
+import org.apache.tuscany.core.component.InstanceFactory;
+import org.apache.tuscany.core.model.physical.java.JavaPhysicalComponentDefinition;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.physical.PhysicalComponentBuilder;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.ScopeRegistry;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.services.classloading.ClassLoaderRegistry;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * Java physical component builder.
+ *
+ * @version $Rev$ $Date$
+ *
+ */
+public class JavaPhysicalComponentBuilder implements
+ PhysicalComponentBuilder<JavaPhysicalComponentDefinition, JavaComponent> {
+
+ // Classloader registry
+ private ClassLoaderRegistry classLoaderRegistry;
+
+ // SCope registry
+ private ScopeRegistry scopeRegistry;
+
+ /**
+ * Builds a component from its physical component definition.
+ *
+ * @param componentDefinition Physical component definition of the component
+ * to be built.
+ * @return A component instance that is ready to go live.
+ * @throws BuilderException If unable to build the component.
+ */
+ public JavaComponent build(JavaPhysicalComponentDefinition componentDefinition) throws BuilderException {
+
+ JavaComponent component = new JavaComponent();
+
+ setScopeContainer(componentDefinition, component);
+
+ setInstanceFactoryClass(componentDefinition, component);
+
+ return component;
+ }
+
+ /**
+ * Injects classloader registry.
+ * @param classLoaderRegistry Class loader registry.
+ */
+ @Reference
+ public void setClassLoaderRegistry(ClassLoaderRegistry classLoaderRegistry) {
+ this.classLoaderRegistry = classLoaderRegistry;
+ }
+
+ /**
+ * Injects scope registry.
+ * @param scopeRegistry Scope registry.
+ */
+ @Reference
+ public void setScopeRegistry(ScopeRegistry scopeRegistry) {
+ this.scopeRegistry = scopeRegistry;
+ }
+
+ /*
+ * Sets the instance factory class.
+ */
+ private void setInstanceFactoryClass(JavaPhysicalComponentDefinition componentDefinition, JavaComponent component) {
+ // TODO use MPCL to load IF class
+ URI classLoaderId = componentDefinition.getClassLoaderId();
+ byte[] instanceFactoryByteCode = componentDefinition.getInstanceFactoryByteCode(); //NOPMD
+ ClassLoader appCl = classLoaderRegistry.getClassLoader(classLoaderId); //NOPMD
+ ClassLoader systemCl = getClass().getClassLoader(); //NOPMD
+ ClassLoader mpcl = null; //NOPMD
+ Class<InstanceFactory<?>> instanceFactoryClass = null;
+ component.setInstanceFactoryClass(instanceFactoryClass);
+ }
+
+ /*
+ * Set the scope container.
+ */
+ private void setScopeContainer(JavaPhysicalComponentDefinition componentDefinition, JavaComponent component) {
+ Scope scope = componentDefinition.getScope();
+ ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(scope);
+ component.setScopeContainer(scopeContainer);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java
new file mode 100644
index 0000000000..2bf602732d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.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.core.implementation.java;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import org.osoa.sca.NoRegisteredCallbackException;
+
+import org.apache.tuscany.spi.component.ComponentException;
+import org.apache.tuscany.spi.component.InvalidConversationSequenceException;
+import org.apache.tuscany.spi.component.TargetException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.extension.TargetInvokerExtension;
+import org.apache.tuscany.spi.model.Scope;
+
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.findClosestMatchingMethod;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods;
+
+/**
+ * Responsible for synchronously dispatching an invocation to a Java component implementation instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaTargetInvoker extends TargetInvokerExtension {
+ protected Method operation;
+ protected JavaAtomicComponent component;
+ protected Object target;
+ protected Class callbackClass;
+ protected boolean stateless;
+
+ public JavaTargetInvoker(Method operation, JavaAtomicComponent component, Class clazz, WorkContext context) {
+ super(context);
+ assert operation != null : "Operation method cannot be null";
+ this.operation = operation;
+ this.component = component;
+ stateless = Scope.STATELESS == component.getScope();
+ this.callbackClass = clazz;
+ }
+
+ public JavaTargetInvoker(Method operation, JavaAtomicComponent component, WorkContext context) {
+ this(operation, component, null, context);
+ }
+
+ public Object invokeTarget(final Object payload, final short sequence) throws InvocationTargetException {
+ try {
+ Object instance = getInstance(sequence);
+ if (callbackClass != null && !callbackClass.isInstance(instance)) {
+ throw new InvocationTargetException(
+ new NoRegisteredCallbackException("Instance is does not implement callback ["
+ + callbackClass.toString() + "]"));
+ }
+ if (!operation.getDeclaringClass().isInstance(instance)) {
+ Set<Method> methods = getAllUniquePublicProtectedMethods(instance.getClass());
+ Method newOperation = findClosestMatchingMethod(operation.getName(),
+ operation.getParameterTypes(), methods);
+ if (newOperation != null) {
+ operation = newOperation;
+ }
+ }
+ Object ret;
+ if (payload != null && !payload.getClass().isArray()) {
+ ret = operation.invoke(instance, payload);
+ } else {
+ ret = operation.invoke(instance, (Object[]) payload);
+ }
+ if (stateless) {
+ // notify a stateless instance of a destruction event after the invoke
+ component.destroy(instance);
+ } else if (sequence == END) {
+ component.destroy(instance);
+ // if end conversation, remove resource
+ component.removeInstance();
+ }
+ return ret;
+ } catch (IllegalAccessException e) {
+ throw new InvocationTargetException(e);
+ } catch (ComponentException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+
+ @Override
+ public JavaTargetInvoker clone() throws CloneNotSupportedException {
+ try {
+ JavaTargetInvoker invoker = (JavaTargetInvoker) super.clone();
+ invoker.target = null;
+ return invoker;
+ } catch (CloneNotSupportedException e) {
+ return null; // will not happen
+ }
+ }
+
+ /**
+ * Resolves the target service instance or returns a cached one
+ */
+ protected Object getInstance(short sequence) throws TargetException {
+ if (!cacheable) {
+ if (sequence == START || sequence == NONE) {
+ return component.getTargetInstance();
+ } else if (sequence == CONTINUE || sequence == END) {
+ return component.getAssociatedTargetInstance();
+ } else {
+ throw new InvalidConversationSequenceException("Unknown sequence type", String.valueOf(sequence));
+ }
+ } else {
+ assert sequence == NONE; // conversations are not cacheable
+ if (target == null) {
+ target = component.getTargetInstance();
+ }
+ return target;
+ }
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/TargetMethodNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/TargetMethodNotFoundException.java
new file mode 100644
index 0000000000..e98f4b3329
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/java/TargetMethodNotFoundException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.implementation.java;
+
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import org.apache.tuscany.spi.model.Operation;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class TargetMethodNotFoundException extends TargetInvokerCreationException {
+ private Operation operation;
+
+ public TargetMethodNotFoundException(Operation operation) {
+ super("Target method not found for operation");
+ this.operation = operation;
+ }
+
+ public Operation getOperation() {
+ return operation;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java
new file mode 100644
index 0000000000..5d90b49362
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.osoa.sca.annotations.AllowsPassByReference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Processes {@link AllowsPassByReference} on an implementation
+ *
+ * @version $Rev: 479093 $ $Date: 2006-11-25 12:34:41 +0530 (Sat, 25 Nov 2006) $
+ */
+public class AllowsPassByReferenceProcessor extends ImplementationProcessorExtension {
+
+ public <T> void visitClass(Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ AllowsPassByReference annotation = clazz.getAnnotation(AllowsPassByReference.class);
+ if (annotation == null) {
+ return;
+ } else {
+ // TODO implement
+ }
+
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java
new file mode 100644
index 0000000000..03d092880d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when constructor parameters cannot be unambiguously resolved to a property or reference
+ *
+ * @version $Rev$ $Date$
+ */
+public class AmbiguousConstructorException extends ProcessingException {
+
+ public AmbiguousConstructorException(String message) {
+ super(message);
+ }
+
+ public AmbiguousConstructorException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ public AmbiguousConstructorException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java
new file mode 100644
index 0000000000..04598199c5
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java
@@ -0,0 +1,112 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.util.List;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ConstructorDefinition;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+
+/**
+ * Handles processing of a constructor decorated with {@link org.osoa.sca.annotations.Constructor}
+ *
+ * @version $Rev$ $Date$
+ */
+@SuppressWarnings("unchecked")
+public class ConstructorProcessor extends ImplementationProcessorExtension {
+
+ private ImplementationProcessorService service;
+
+ public ConstructorProcessor(@Reference ImplementationProcessorService service) {
+ this.service = service;
+ }
+
+ public <T> void visitClass(Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ Constructor[] ctors = clazz.getConstructors();
+ boolean found = false;
+ for (Constructor constructor : ctors) {
+ if (constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) {
+ if (found) {
+ String name = constructor.getDeclaringClass().getName();
+ throw new DuplicateConstructorException("Multiple constructors marked with @Constructor", name);
+ }
+ found = true;
+ }
+ }
+ }
+
+ public <T> void visitConstructor(Constructor<T> constructor,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ org.osoa.sca.annotations.Constructor annotation =
+ constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class);
+ if (annotation == null) {
+ return;
+ }
+ ConstructorDefinition<?> definition = type.getConstructorDefinition();
+ if (definition != null && !definition.getConstructor().equals(constructor)) {
+ String name = constructor.getDeclaringClass().getName();
+ throw new DuplicateConstructorException("Multiple constructor definitions found", name);
+ } else if (definition == null) {
+ definition = new ConstructorDefinition(constructor);
+ }
+ Class<?>[] params = constructor.getParameterTypes();
+ String[] names = annotation.value();
+ Annotation[][] annotations = constructor.getParameterAnnotations();
+ List<String> injectionNames = definition.getInjectionNames();
+ for (int i = 0; i < params.length; i++) {
+ Class<?> param = params[i];
+ Annotation[] paramAnnotations = annotations[i];
+ try {
+ if (!service.processParam(param,
+ constructor.getGenericParameterTypes()[i],
+ paramAnnotations,
+ names,
+ i,
+ type,
+ injectionNames)) {
+ String name = (i < names.length) ? names[i] : "";
+ service.addName(injectionNames, i, name);
+ }
+ } catch (ProcessingException e) {
+ e.setMember(constructor);
+ throw e;
+ }
+ }
+ if (names.length != 0 && names[0].length() != 0 && names.length != params.length) {
+ throw new InvalidConstructorException("Names in @Constructor do not match number of parameters");
+ }
+ type.setConstructorDefinition(definition);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java
new file mode 100644
index 0000000000..a0d462b660
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java
@@ -0,0 +1,103 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.osoa.sca.ComponentContext;
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.annotations.Context;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.implementation.java.Resource;
+
+import org.apache.tuscany.core.injection.RequestContextObjectFactory;
+import org.apache.tuscany.core.util.JavaIntrospectionHelper;
+
+/**
+ * Processes {@link @Context} annotations on a component implementation and adds a {@link JavaMappedProperty} to the
+ * component type which will be used to inject the appropriate context
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContextProcessor extends ImplementationProcessorExtension {
+ private WorkContext workContext;
+
+ @Reference
+ public void setWorkContext(WorkContext workContext) {
+ this.workContext = workContext;
+ }
+
+ public void visitMethod(
+ Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ if (method.getAnnotation(Context.class) == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalContextException("Context setter must have one parameter", method.toString());
+ }
+ Class<?> paramType = method.getParameterTypes()[0];
+ if (ComponentContext.class.equals(paramType)) {
+ String name = JavaIntrospectionHelper.toPropertyName(method.getName());
+ Resource<ComponentContext> resource = new Resource<ComponentContext>(name, ComponentContext.class, method);
+ type.getResources().put(name, resource);
+ } else if (RequestContext.class.equals(paramType)) {
+ String name = JavaIntrospectionHelper.toPropertyName(method.getName());
+ Resource<RequestContext> resource = new Resource<RequestContext>(name, RequestContext.class, method);
+ resource.setObjectFactory(new RequestContextObjectFactory(workContext));
+ type.getResources().put(name, resource);
+ } else {
+ throw new UnknownContextTypeException(paramType.getName());
+ }
+ }
+
+ public void visitField(Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ if (field.getAnnotation(Context.class) == null) {
+ return;
+ }
+ Class<?> paramType = field.getType();
+ if (ComponentContext.class.equals(paramType)) {
+ String name = field.getName();
+ Resource<ComponentContext> resource = new Resource<ComponentContext>(name, ComponentContext.class, field);
+ type.getResources().put(name, resource);
+ } else if (RequestContext.class.equals(paramType)) {
+ String name = field.getName();
+ name = JavaIntrospectionHelper.toPropertyName(name);
+ Resource<RequestContext> resource = new Resource<RequestContext>(name, RequestContext.class, field);
+ resource.setObjectFactory(new RequestContextObjectFactory(workContext));
+ type.getResources().put(name, resource);
+ } else {
+ throw new UnknownContextTypeException(paramType.getName());
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java
new file mode 100644
index 0000000000..9d81e15ba1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java
@@ -0,0 +1,141 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.osoa.sca.annotations.ConversationAttributes;
+import org.osoa.sca.annotations.ConversationID;
+import org.osoa.sca.annotations.Scope;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ConversationProcessor extends ImplementationProcessorExtension {
+ private static final String SECONDS = " SECONDS";
+ private static final String MINUTES = " MINUTES";
+ private static final String HOURS = " HOURS";
+ private static final String DAYS = " DAYS";
+ private static final String YEARS = " YEARS";
+
+ public <T> void visitClass(Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ ConversationAttributes conversation = clazz.getAnnotation(ConversationAttributes.class);
+ if (conversation == null) {
+ return;
+ }
+ Scope scope = clazz.getAnnotation(Scope.class);
+ if (scope == null) {
+ // implicitly assume conversation
+ type.setImplementationScope(org.apache.tuscany.spi.model.Scope.CONVERSATION);
+ } else if (scope != null && !"CONVERSATION".equals(scope.value().toUpperCase())) {
+ throw new InvalidConversationalImplementation(
+ "Service is marked with @ConversationAttributes but the scope is not @Scope(\"CONVERSATION\")",
+ clazz.getName());
+ } else if (conversation != null) {
+ long maxAge;
+ long maxIdleTime;
+ String maxAgeVal = conversation.maxAge();
+ String maxIdleTimeVal = conversation.maxIdleTime();
+ if (maxAgeVal.length() > 0 && maxIdleTimeVal.length() > 0) {
+ throw new InvalidConversationalImplementation("Max idle time and age both specified", clazz.getName());
+ }
+ try {
+ if (maxAgeVal.length() > 0) {
+ maxAge = convertTimeMillis(maxAgeVal);
+ type.setMaxAge(maxAge);
+ }
+ } catch (NumberFormatException e) {
+ throw new InvalidConversationalImplementation("Invalid maximum age", clazz.getName(), e);
+ }
+ try {
+ if (maxIdleTimeVal.length() > 0) {
+ maxIdleTime = convertTimeMillis(maxIdleTimeVal);
+ type.setMaxIdleTime(maxIdleTime);
+ }
+ } catch (NumberFormatException e) {
+ throw new InvalidConversationalImplementation("Invalid maximum idle time", clazz.getName(), e);
+ }
+ }
+
+ }
+
+ public void visitMethod(Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ ConversationID conversationID = method.getAnnotation(ConversationID.class);
+ if (conversationID == null) {
+ return;
+ }
+ type.setConversationIDMember(method);
+ }
+
+ public void visitField(Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ ConversationID conversationID = field.getAnnotation(ConversationID.class);
+ if (conversationID == null) {
+ return;
+ }
+ type.setConversationIDMember(field);
+ }
+
+ protected long convertTimeMillis(String expr) throws NumberFormatException {
+ expr = expr.trim().toUpperCase();
+ int i = expr.lastIndexOf(SECONDS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 1000;
+ }
+ i = expr.lastIndexOf(MINUTES);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 60000;
+ }
+
+ i = expr.lastIndexOf(HOURS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 3600000;
+ }
+ i = expr.lastIndexOf(DAYS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 86400000;
+ }
+ i = expr.lastIndexOf(YEARS);
+ if (i >= 0) {
+ String units = expr.substring(0, i);
+ return Long.parseLong(units) * 31556926000L;
+ }
+ return Long.parseLong(expr) * 1000; // assume seconds if no suffix specified
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java
new file mode 100644
index 0000000000..0b4e8eff76
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.processor;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.osoa.sca.annotations.Destroy;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Processes the {@link @Destroy} annotation on a component implementation and updates the component type with the
+ * decorated destructor method
+ *
+ * @version $Rev$ $Date$
+ */
+public class DestroyProcessor extends ImplementationProcessorExtension {
+
+ public void visitMethod(Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ Destroy annotation = method.getAnnotation(Destroy.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 0) {
+ throw new IllegalDestructorException("Destructor must not have argments", method.toString());
+ }
+ if (type.getDestroyMethod() != null) {
+ throw new DuplicateDestructorException("More than one destructor found on implementation");
+ }
+ if (Modifier.isProtected(method.getModifiers())) {
+ method.setAccessible(true);
+ }
+ type.setDestroyMethod(method);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java
new file mode 100644
index 0000000000..88db7ebb79
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when more than one component implementation constructor is annotated with {@link
+ * org.osoa.sca.annotations.Constructor}
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateConstructorException extends ProcessingException {
+
+ public DuplicateConstructorException(String message) {
+ super(message);
+ }
+
+ public DuplicateConstructorException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java
new file mode 100644
index 0000000000..6225bd6219
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when an implementation is annotated multiple times with {@link org.osoa.sca.annotations.Destroy}
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateDestructorException extends ProcessingException {
+
+ public DuplicateDestructorException(String message) {
+ super(message);
+ }
+
+ public DuplicateDestructorException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java
new file mode 100644
index 0000000000..105edee1a2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when an implementation is annotated multiple times with {@link @org.osoa.sca.annotations.Init}
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateInitException extends ProcessingException {
+
+ public DuplicateInitException(String message) {
+ super(message);
+ }
+
+ public DuplicateInitException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java
new file mode 100644
index 0000000000..5eae1461c2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when an implementation has more than one reference injection site with the same name
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateReferenceException extends ProcessingException {
+
+ public DuplicateReferenceException(String message) {
+ super(message);
+ }
+
+
+ public DuplicateReferenceException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java
new file mode 100644
index 0000000000..9dd718c03e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when an implementation has more than one resource injection site with the same name
+ *
+ * @version $Rev$ $Date$
+ */
+public class DuplicateResourceException extends ProcessingException {
+
+ public DuplicateResourceException(String message) {
+ super(message);
+ }
+
+ public DuplicateResourceException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java
new file mode 100644
index 0000000000..cdf39013a1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java
@@ -0,0 +1,58 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Handles processing of {@link org.osoa.sca.annotations.EagerInit}
+ *
+ * @version $Rev$ $Date$
+ */
+public class EagerInitProcessor extends ImplementationProcessorExtension {
+
+ public <T> void visitClass(Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ super.visitClass(clazz, type, context);
+ EagerInit annotation = clazz.getAnnotation(EagerInit.class);
+ if (annotation == null) {
+ Class<?> superClass = clazz.getSuperclass();
+ while (!Object.class.equals(superClass)) {
+ annotation = superClass.getAnnotation(EagerInit.class);
+ if (annotation != null) {
+ break;
+ }
+ superClass = superClass.getSuperclass();
+ }
+ if (annotation == null) {
+ return;
+ }
+ }
+ type.setInitLevel(50);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java
new file mode 100644
index 0000000000..ab125d5ca1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java
@@ -0,0 +1,548 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.model.TypeInfo;
+import org.apache.tuscany.spi.implementation.java.ConstructorDefinition;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllInterfaces;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllPublicAndProtectedFields;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName;
+
+/**
+ * Heuristically evaluates an un-annotated Java implementation type to determine services, references, and properties
+ * according to the algorithm described in the SCA Java Client and Implementation Model Specification <p/> TODO
+ * Implement:
+ * <p/>
+ * When no service inteface is annotated, need to calculate a single service comprising all public methods that are not
+ * reference or property injection sites. If that service can be exactly mapped to an interface implemented by the class
+ * then the service interface will be defined in terms of that interface.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeuristicPojoProcessor extends ImplementationProcessorExtension {
+ private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension();
+ private ImplementationProcessorService implService;
+
+ public HeuristicPojoProcessor(@Reference ImplementationProcessorService service) {
+ this.implService = service;
+ }
+
+ public <T> void visitEnd(
+ Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ Map<String, JavaMappedService> services = type.getServices();
+ if (services.isEmpty()) {
+ // heuristically determine the service
+ // TODO finish algorithm
+ Set<Class> interfaces = getAllInterfaces(clazz);
+ if (interfaces.size() == 0) {
+ // class is the interface
+ JavaMappedService service;
+ try {
+ service = implService.createService(clazz);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getServices().put(service.getUri().getFragment(), service);
+ } else if (interfaces.size() == 1) {
+ JavaMappedService service;
+ try {
+ service = implService.createService(interfaces.iterator().next());
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getServices().put(service.getUri().getFragment(), service);
+ }
+ }
+ Set<Method> methods = getAllUniquePublicProtectedMethods(clazz);
+ if (!type.getReferences().isEmpty() || !type.getProperties().isEmpty()) {
+ // references and properties have been explicitly defined
+ if (type.getServices().isEmpty()) {
+ calculateServiceInterface(clazz, type, methods);
+ if (type.getServices().isEmpty()) {
+ throw new ServiceTypeNotFoundException(clazz.getName());
+ }
+ }
+ evaluateConstructor(type, clazz);
+ return;
+ }
+ calcPropRefs(methods, services, type, clazz);
+ evaluateConstructor(type, clazz);
+ }
+
+ private <T> void calcPropRefs(Set<Method> methods,
+ Map<String, JavaMappedService> services,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Class<T> clazz) throws ProcessingException {
+ // heuristically determine the properties references
+ // make a first pass through all public methods with one param
+ for (Method method : methods) {
+ if (method.getParameterTypes().length != 1 || !Modifier.isPublic(method.getModifiers())
+ || !method.getName().startsWith("set")
+ || method.getReturnType() != void.class) {
+ continue;
+ }
+ if (!isInServiceInterface(method, services)) {
+ String name = toPropertyName(method.getName());
+ // avoid duplicate property or ref names
+ if (!type.getProperties().containsKey(name) && !type.getReferences().containsKey(name)) {
+ Class<?> param = method.getParameterTypes()[0];
+ Type genericType = method.getGenericParameterTypes()[0];
+ if (isReferenceType(genericType)) {
+ type.add(createReference(name, method, param));
+ } else {
+ type.add(createProperty(name, method, param));
+ }
+ }
+ }
+ }
+ // second pass for protected methods with one param
+ for (Method method : methods) {
+ if (method.getParameterTypes().length != 1 || !Modifier.isProtected(method.getModifiers())
+ || !method.getName().startsWith("set")
+ || method.getReturnType() != void.class) {
+ continue;
+ }
+ Class<?> param = method.getParameterTypes()[0];
+ String name = toPropertyName(method.getName());
+ // avoid duplicate property or ref names
+ if (!type.getProperties().containsKey(name) && !type.getReferences().containsKey(name)) {
+ if (isReferenceType(param)) {
+ type.add(createReference(name, method, param));
+ } else {
+ type.add(createProperty(name, method, param));
+ }
+ }
+ }
+ Set<Field> fields = getAllPublicAndProtectedFields(clazz);
+ for (Field field : fields) {
+ Class<?> paramType = field.getType();
+ if (isReferenceType(paramType)) {
+ type.add(createReference(field.getName(), field, paramType));
+ } else {
+ type.add(createProperty(field.getName(), field, paramType));
+ }
+ }
+ }
+
+ /**
+ * Determines the constructor to use based on the component type's references and properties
+ *
+ * @param type the component type
+ * @param clazz the implementation class corresponding to the component type
+ * @throws NoConstructorException if no suitable constructor is found
+ * @throws AmbiguousConstructorException if the parameters of a constructor cannot be unambiguously mapped to
+ * references and properties
+ */
+ @SuppressWarnings("unchecked")
+ private <T> void evaluateConstructor(
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Class<T> clazz) throws ProcessingException {
+ // determine constructor if one is not annotated
+ ConstructorDefinition<?> definition = type.getConstructorDefinition();
+ Constructor constructor;
+ boolean explict = false;
+ if (definition != null
+ && definition.getConstructor().getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) {
+ // the constructor was already defined explicitly
+ return;
+ } else if (definition != null) {
+ explict = true;
+ constructor = definition.getConstructor();
+ } else {
+ // no definition, heuristically determine constructor
+ Constructor[] constructors = clazz.getConstructors();
+ if (constructors.length == 0) {
+ throw new NoConstructorException("No public constructor for class", clazz.getName());
+ } else if (constructors.length == 1) {
+ constructor = constructors[0];
+ } else {
+ // FIXME multiple constructors, none yet done
+ Constructor<T> selected = null;
+ int sites = type.getProperties().size() + type.getReferences().size();
+ for (Constructor<T> ctor : constructors) {
+ if (ctor.getParameterTypes().length == 0) {
+ selected = ctor;
+ }
+ if (ctor.getParameterTypes().length == sites) {
+ // TODO finish
+ // selected = constructor;
+ // select constructor
+ // break;
+ }
+ }
+ if (selected == null) {
+ throw new NoConstructorException();
+ }
+ constructor = selected;
+ definition = new ConstructorDefinition<T>(selected);
+ type.setConstructorDefinition(definition);
+ // return;
+ }
+ definition = new ConstructorDefinition<T>(constructor);
+ type.setConstructorDefinition(definition);
+ }
+ Class[] params = constructor.getParameterTypes();
+ if (params.length == 0) {
+ return;
+ }
+ List<String> paramNames = definition.getInjectionNames();
+ Map<String, JavaMappedProperty<?>> props = type.getProperties();
+ Map<String, JavaMappedReference> refs = type.getReferences();
+ Annotation[][] annotations = constructor.getParameterAnnotations();
+ if (!explict) {
+ // the constructor wasn't defined by an annotation, so check to see if any of the params have an annotation
+ // which we can impute as explicitly defining the constructor, e.g. @Property, @Reference, or @Autowire
+ explict = implService.injectionAnnotationsPresent(annotations);
+ }
+ if (explict) {
+ for (int i = 0; i < params.length; i++) {
+ Class param = params[i];
+ implService.processParam(param,
+ constructor.getGenericParameterTypes()[i],
+ annotations[i],
+ new String[0],
+ i,
+ type,
+ paramNames);
+ }
+ } else {
+ if (!implService.areUnique(params)) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!calcPropRefUniqueness(props.values(), refs.values())) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ boolean empty = props.size() + refs.size() == 0;
+ if (!empty) {
+ calcParamNames(params, props, refs, paramNames);
+ } else {
+ heuristicParamNames(params, refs, props, paramNames);
+
+ }
+ }
+ }
+
+ private void calcParamNames(Class[] params,
+ Map<String, JavaMappedProperty<?>> props,
+ Map<String, JavaMappedReference> refs,
+ List<String> paramNames)
+ throws AmbiguousConstructorException {
+ // the constructor param types must unambiguously match defined reference or property types
+ for (Class param : params) {
+ String name = findReferenceOrProperty(param, props, refs);
+ if (name == null) {
+ throw new AmbiguousConstructorException(param.getName());
+ }
+ paramNames.add(name);
+ }
+ }
+
+ private void heuristicParamNames(Class[] params,
+ Map<String, JavaMappedReference> refs,
+ Map<String, JavaMappedProperty<?>> props,
+ List<String> paramNames)
+ throws ProcessingException {
+ // heuristically determine refs and props from the parameter types
+ for (Class<?> param : params) {
+ String name = getBaseName(param).toLowerCase();
+ if (isReferenceType(param)) {
+ refs.put(name, createReference(name, null, param));
+ } else {
+ props.put(name, createProperty(name, null, param));
+ }
+ paramNames.add(name);
+ }
+ }
+
+ /**
+ * Returns true if the union of the given collections of properties and references have unique Java types
+ */
+ private boolean calcPropRefUniqueness(
+ Collection<JavaMappedProperty<?>> props,
+ Collection<JavaMappedReference> refs) {
+
+ Class[] classes = new Class[props.size() + refs.size()];
+ int i = 0;
+ for (JavaMappedProperty<?> property : props) {
+ classes[i] = property.getJavaType();
+ i++;
+ }
+ for (JavaMappedReference reference : refs) {
+ classes[i] = reference.getServiceContract().getInterfaceClass();
+ i++;
+ }
+ return implService.areUnique(classes);
+ }
+
+ /**
+ * Unambiguously finds the reference or property associated with the given type
+ *
+ * @return the name of the reference or property if found, null if not
+ * @throws AmbiguousConstructorException if the constructor parameter cannot be resolved to a property or reference
+ */
+ private String findReferenceOrProperty(
+ Class<?> type,
+ Map<String, JavaMappedProperty<?>> props,
+ Map<String, JavaMappedReference> refs) throws AmbiguousConstructorException {
+
+ String name = null;
+ for (JavaMappedProperty<?> property : props.values()) {
+ if (property.getJavaType().equals(type)) {
+ if (name != null) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ type.getName());
+ }
+ name = property.getName();
+ // do not break since ambiguities must be checked, i.e. more than one prop or ref of the same type
+ }
+ }
+ for (JavaMappedReference reference : refs.values()) {
+ if (reference.getServiceContract().getInterfaceClass().equals(type)) {
+ if (name != null) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ type.getName());
+ }
+ name = reference.getUri().getFragment();
+ // do not break since ambiguities must be checked, i.e. more than one prop or ref of the same type
+ }
+ }
+ return name;
+ }
+
+ /**
+ * Returns true if a given type is reference according to the SCA specification rules for determining reference
+ * types
+ */
+ private boolean isReferenceType(Type operationType) {
+ Class<?> rawType;
+ Class<?> referenceType = null;
+ if (operationType instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) operationType;
+ rawType = (Class<?>) parameterizedType.getRawType();
+ Type[] typeArgs = parameterizedType.getActualTypeArguments();
+ if (typeArgs.length == 1) {
+ referenceType = (Class<?>) typeArgs[0];
+ }
+ } else {
+ rawType = (Class<?>) operationType;
+ }
+ if (rawType.isArray()) {
+ referenceType = rawType.getComponentType();
+ } else if (Collection.class.isAssignableFrom(rawType) && referenceType == null) {
+ return true;
+ }
+ if (referenceType != null) {
+ return referenceType.getAnnotation(Remotable.class) != null
+ || referenceType.getAnnotation(Service.class) != null;
+ } else {
+ return rawType.getAnnotation(Remotable.class) != null || rawType.getAnnotation(Service.class) != null;
+ }
+ }
+
+ /**
+ * Returns true if the given operation is defined in the collection of service interfaces
+ */
+ private boolean isInServiceInterface(Method operation, Map<String, JavaMappedService> services) {
+ for (JavaMappedService service : services.values()) {
+ Class<?> clazz = service.getServiceContract().getInterfaceClass();
+ if (operation.getDeclaringClass().equals(clazz)) {
+ return true;
+ }
+ Method[] methods = service.getServiceContract().getInterfaceClass().getMethods();
+ for (Method method : methods) {
+ if (operation.getName().equals(method.getName())
+ && operation.getParameterTypes().length == method.getParameterTypes().length) {
+ Class<?>[] methodTypes = method.getParameterTypes();
+ for (int i = 0; i < operation.getParameterTypes().length; i++) {
+ Class<?> paramType = operation.getParameterTypes()[i];
+ if (!paramType.equals(methodTypes[i])) {
+ break;
+ } else if (i == operation.getParameterTypes().length - 1) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a mapped reference
+ *
+ * @param name the reference name
+ * @param member the injection site the reference maps to
+ * @param paramType the service interface of the reference
+ */
+ private JavaMappedReference createReference(String name, Member member, Class<?> paramType)
+ throws ProcessingException {
+ return implService.createReference(name, member, paramType);
+ }
+
+ /**
+ * Creates a mapped property
+ *
+ * @param name the property name
+ * @param member the injection site the reference maps to
+ * @param paramType the property type
+ */
+ private <T> JavaMappedProperty<T> createProperty(String name, Member member, Class<T> paramType) {
+ JavaMappedProperty<T> property = new JavaMappedProperty<T>();
+ property.setName(name);
+ property.setMember(member);
+ property.setJavaType(paramType);
+ TypeInfo xmlType = typeMapper.getXMLType(paramType);
+ if (xmlType != null) {
+ property.setXmlType(xmlType.getQName());
+ }
+
+ return property;
+ }
+
+ /**
+ * Populates a component type with a service whose interface type is determined by examining all implemented
+ * interfaces of the given class and chosing one whose operations match all of the class's non-property and
+ * non-reference methods
+ *
+ * @param clazz the class to examine
+ * @param type the component type
+ * @param methods all methods in the class to examine
+ */
+ private void calculateServiceInterface(
+ Class<?> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Set<Method> methods) throws ProcessingException {
+ List<Method> nonPropRefMethods = new ArrayList<Method>();
+ // Map<String, JavaMappedService> services = type.getServices();
+ Map<String, JavaMappedReference> references = type.getReferences();
+ Map<String, JavaMappedProperty<?>> properties = type.getProperties();
+ // calculate methods that are not properties or references
+ for (Method method : methods) {
+ String name = toPropertyName(method.getName());
+ if (!references.containsKey(name) && !properties.containsKey(name)) {
+ nonPropRefMethods.add(method);
+ }
+ }
+ // determine if an implemented interface matches all of the non-property and non-reference methods
+ Class[] interfaces = clazz.getInterfaces();
+ if (interfaces.length == 0) {
+ return;
+ }
+ for (Class interfaze : interfaces) {
+ if (analyzeInterface(interfaze, nonPropRefMethods)) {
+ JavaMappedService service;
+ try {
+ service = implService.createService(interfaze);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getServices().put(service.getUri().getFragment(), service);
+ }
+ }
+ }
+
+ /**
+ * Determines if the methods of a given interface match the given list of methods
+ *
+ * @param interfaze the interface to examine
+ * @param nonPropRefMethods the list of methods to match against
+ * @return true if the interface matches
+ */
+ private boolean analyzeInterface(Class<?> interfaze, List<Method> nonPropRefMethods) {
+ Method[] interfaceMethods = interfaze.getMethods();
+ if (nonPropRefMethods.size() != interfaceMethods.length) {
+ return false;
+ }
+ for (Method method : nonPropRefMethods) {
+ boolean found = false;
+ for (Method interfaceMethod : interfaceMethods) {
+ if (interfaceMethod.getName().equals(method.getName())) {
+ Class<?>[] interfaceParamTypes = interfaceMethod.getParameterTypes();
+ Class<?>[] methodParamTypes = method.getParameterTypes();
+ if (interfaceParamTypes.length == methodParamTypes.length) {
+ if (interfaceParamTypes.length == 0) {
+ found = true;
+ } else {
+ for (int i = 0; i < methodParamTypes.length; i++) {
+ Class<?> param = methodParamTypes[i];
+ if (!param.equals(interfaceParamTypes[i])) {
+ break;
+ }
+ if (i == methodParamTypes.length - 1) {
+ found = true;
+ }
+ }
+ }
+ }
+ if (found) {
+ break;
+ }
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
+
+/*
+ * 1) public setter methods that are not included in any service interface 2) protected setter methods 3) public or
+ * protected fields unless there is a setter method for the same name If the type associated with the member is an array
+ * or a java.util.Collection, then the basetype will be the element type of the array or the parameterized type of the
+ * Collection, otherwise the basetype will be the member type. If the basetype is an interface with an @Remotable or
+ * @Service annotation then the member will be defined as a reference, otherwise it will be defined as a property.
+ *
+ *
+ */
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java
new file mode 100644
index 0000000000..4581faa872
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegcal use of {@link org.osoa.sca.annotations.Callback} on a reference
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalCallbackReferenceException extends ProcessingException {
+
+ public IllegalCallbackReferenceException(String message) {
+ super(message);
+ }
+
+ public IllegalCallbackReferenceException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java
new file mode 100644
index 0000000000..8c56cade83
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Context}
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalContextException extends ProcessingException {
+
+ public IllegalContextException(String message) {
+ super(message);
+ }
+
+ public IllegalContextException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java
new file mode 100644
index 0000000000..fee42ea5c8
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Destroy}
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalDestructorException extends ProcessingException {
+
+ public IllegalDestructorException(String message) {
+ super(message);
+ }
+
+ public IllegalDestructorException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java
new file mode 100644
index 0000000000..219074b785
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegal signature for a method decorated with {@link @org.osoa.sca.annotations.Init}
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalInitException extends ProcessingException {
+ public IllegalInitException(String message) {
+ super(message);
+ }
+
+ public IllegalInitException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java
new file mode 100644
index 0000000000..11137bcaba
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegal reference definition in a component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalReferenceException extends ProcessingException {
+
+ public IllegalReferenceException(String message) {
+ super(message);
+ }
+
+ public IllegalReferenceException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java
new file mode 100644
index 0000000000..e25c1174e2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegal resource definition in a component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalResourceException extends ProcessingException {
+
+ public IllegalResourceException(String message) {
+ super(message);
+ }
+
+ public IllegalResourceException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java
new file mode 100644
index 0000000000..1d9079636a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an illegal use of the {@link @org.osoa.sca.annotations.Service} annotation
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalServiceDefinitionException extends ProcessingException {
+
+ public IllegalServiceDefinitionException(String message) {
+ super(message);
+ }
+
+ public IllegalServiceDefinitionException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java
new file mode 100644
index 0000000000..ccc947f58a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java
@@ -0,0 +1,384 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.Collection;
+import java.util.List;
+
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.model.TypeInfo;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
+import org.apache.tuscany.spi.implementation.java.DuplicatePropertyException;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+import org.apache.tuscany.api.annotation.Resource;
+import org.apache.tuscany.core.idl.java.IllegalCallbackException;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName;
+
+/**
+ * The default implementation of an <code>ImplementationProcessorService</code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class ImplementationProcessorServiceImpl implements ImplementationProcessorService {
+ private JavaInterfaceProcessorRegistry registry;
+ private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension();
+
+ public ImplementationProcessorServiceImpl(@Reference JavaInterfaceProcessorRegistry registry) {
+ this.registry = registry;
+ }
+
+ public JavaMappedService createService(Class<?> interfaze) throws InvalidServiceContractException {
+ JavaMappedService service = new JavaMappedService();
+ // create a relative URI
+ service.setUri(URI.create("#" + interfaze.getSimpleName()));
+ service.setRemotable(interfaze.getAnnotation(Remotable.class) != null);
+ ServiceContract<?> contract = registry.introspect(interfaze);
+ service.setServiceContract(contract);
+ return service;
+ }
+
+ public void processCallback(Class<?> interfaze, ServiceContract<?> contract) throws IllegalCallbackException {
+ Callback callback = interfaze.getAnnotation(Callback.class);
+ if (callback != null && !Void.class.equals(callback.value())) {
+ Class<?> callbackClass = callback.value();
+ contract.setCallbackClass(callbackClass);
+ contract.setCallbackName(getBaseName(callbackClass));
+ } else if (callback != null && Void.class.equals(callback.value())) {
+ throw new IllegalCallbackException("No callback interface specified on annotation", interfaze.getName());
+ }
+ }
+
+ public boolean areUnique(Class[] collection) {
+ if (collection.length == 0) {
+ return true;
+ }
+ return areUnique(collection, 0);
+ }
+
+ public void addName(List<String> names, int pos, String name) {
+ if (names.size() < pos) {
+ for (int i = 0; i < pos; i++) {
+ names.add(i, "");
+ }
+ names.add(name);
+ } else if (names.size() > pos) {
+ names.remove(pos);
+ names.add(pos, name);
+ } else {
+ names.add(pos, name);
+ }
+ }
+
+ public boolean processParam(
+ Class<?> param,
+ Type genericParam,
+ Annotation[] paramAnnotations,
+ String[] constructorNames,
+ int pos,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ List<String> injectionNames) throws ProcessingException {
+ boolean processed = false;
+ for (Annotation annot : paramAnnotations) {
+ if (Property.class.equals(annot.annotationType())) {
+ processed = true;
+ processProperty(annot, constructorNames, pos, type, param, genericParam, injectionNames);
+ } else if (Reference.class.equals(annot.annotationType())) {
+ processed = true;
+ processReference(annot, constructorNames, pos, type, param, genericParam, injectionNames);
+ } else if (Resource.class.equals(annot.annotationType())) {
+ processed = true;
+ processResource((Resource) annot, constructorNames, pos, type, param, injectionNames);
+ }
+ }
+ return processed;
+ }
+
+ public boolean injectionAnnotationsPresent(Annotation[][] annots) {
+ for (Annotation[] annotations : annots) {
+ for (Annotation annotation : annotations) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class)
+ || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public JavaMappedReference createReference(String name, Member member, Class<?> paramType)
+ throws ProcessingException {
+ JavaMappedReference reference = new JavaMappedReference();
+ reference.setUri(URI.create("#" + name));
+ reference.setMember(member);
+ reference.setRequired(false);
+ ServiceContract contract;
+ try {
+ contract = registry.introspect(paramType);
+ } catch (InvalidServiceContractException e1) {
+ throw new ProcessingException(e1);
+ }
+ try {
+ processCallback(paramType, contract);
+ } catch (IllegalCallbackException e) {
+ throw new ProcessingException(e);
+ }
+ reference.setServiceContract(contract);
+ return reference;
+ }
+
+ /**
+ * Determines if all the members of a collection have unique types
+ *
+ * @param collection the collection to analyze
+ * @param start the position in the collection to start
+ * @return true if the types are unique
+ */
+ private boolean areUnique(Class[] collection, int start) {
+ Object compare = collection[start];
+ for (int i = start + 1; i < collection.length; i++) {
+ if (compare.equals(collection[i])) {
+ return false;
+ }
+ }
+ if (start + 1 < collection.length) {
+ return areUnique(collection, start + 1);
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Processes parameter metadata for a constructor parameter
+ *
+ * @param annot the parameter annotation
+ * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor}
+ * annotation
+ * @param pos the position of the parameter in the constructor's parameter list
+ * @param type the component type associated with the implementation being processed
+ * @param param the parameter type
+ * @param explicitNames the collection of injection names to update
+ * @throws ProcessingException
+ */
+ @SuppressWarnings("unchecked")
+ private void processProperty(
+ Annotation annot,
+ String[] constructorNames,
+ int pos,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Class<?> param,
+ Type genericParam,
+ List<String> explicitNames) throws ProcessingException {
+ // the param is marked as a property
+ Property propAnnot = (Property) annot;
+ JavaMappedProperty property = new JavaMappedProperty();
+ Class<?> baseType = getBaseType(param, genericParam);
+ if (param.isArray() || Collection.class.isAssignableFrom(param)) {
+ property.setMany(true);
+ }
+ property.setJavaType(baseType);
+ String name = propAnnot.name();
+ if (name == null || name.length() == 0) {
+ if (constructorNames.length < pos + 1 || constructorNames[pos] == null
+ || constructorNames[pos].length() == 0) {
+ throw new InvalidPropertyException("No name specified for property parameter " + (pos + 1));
+ }
+ name = constructorNames[pos];
+ } else if (pos < constructorNames.length && constructorNames[pos] != null
+ && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) {
+ String paramNum = String.valueOf(pos + 1);
+ throw new InvalidConstructorException("Name specified by @Constructor does not match property name",
+ paramNum);
+ }
+ if (type.getProperties().get(name) != null) {
+ throw new DuplicatePropertyException(name);
+ }
+ property.setName(name);
+ property.setRequired(propAnnot.required());
+
+ TypeInfo typeInfo = typeMapper.getXMLType(property.getJavaType());
+ if (typeInfo != null) {
+ property.setXmlType(typeInfo.getQName());
+ }
+ type.getProperties().put(name, property);
+ addName(explicitNames, pos, name);
+ }
+
+ /**
+ * Processes reference metadata for a constructor parameter
+ *
+ * @param annot the parameter annotation
+ * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor}
+ * annotation
+ * @param pos the position of the parameter in the constructor's parameter list
+ * @param type the component type associated with the implementation being processed
+ * @param param the parameter type
+ * @param explicitNames the collection of injection names to update
+ * @throws ProcessingException
+ */
+ private void processReference(
+ Annotation annot,
+ String[] constructorNames,
+ int pos,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Class<?> param,
+ Type genericParam,
+ List<String> explicitNames) throws ProcessingException {
+
+ // TODO multiplicity
+ // the param is marked as a reference
+ Reference refAnnotation = (Reference) annot;
+ JavaMappedReference reference = new JavaMappedReference();
+ String name = refAnnotation.name();
+ if (name == null || name.length() == 0) {
+ if (constructorNames.length == 0 || constructorNames[0].length() == 0) {
+ name = "_ref" + pos;
+ } else if (constructorNames.length < pos + 1 || constructorNames[pos] == null
+ || constructorNames[pos].length() == 0) {
+ throw new InvalidReferenceException("No name specified for reference parameter " + (pos + 1));
+ } else {
+ name = constructorNames[pos];
+ }
+ } else if (pos < constructorNames.length && constructorNames[pos] != null
+ && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) {
+ String paramNum = String.valueOf(pos + 1);
+ throw new InvalidConstructorException("Name specified by @Constructor does not match reference name",
+ paramNum);
+ }
+ if (type.getReferences().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+ reference.setUri(URI.create("#" + name));
+ boolean required = refAnnotation.required();
+ reference.setRequired(required);
+ try {
+ Class<?> rawType = param;
+ if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_N);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_N);
+ }
+ } else {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_ONE);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ }
+ }
+ Class<?> baseType = getBaseType(rawType, genericParam);
+ ServiceContract<?> contract = registry.introspect(baseType);
+ reference.setServiceContract(contract);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getReferences().put(name, reference);
+ addName(explicitNames, pos, name);
+ }
+
+ /**
+ * Processes resource metadata for a constructor parameter
+ *
+ * @param resourceAnnot the resource annotation
+ * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor}
+ * annotation
+ * @param pos the position of the parameter in the constructor's parameter list
+ * @param type the component type associated with the implementation being processed
+ * @param param the parameter type
+ * @param explicitNames the collection of injection names to update
+ * @throws ProcessingException
+ */
+ private <T> void processResource(
+ Resource resourceAnnot,
+ String[] constructorNames,
+ int pos,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Class<T> param,
+ List<String> explicitNames) throws ProcessingException {
+
+ String name = resourceAnnot.name();
+ if (name == null || name.length() == 0) {
+ if (constructorNames.length < pos + 1 || constructorNames[pos] == null
+ || constructorNames[pos].length() == 0) {
+ String paramNum = String.valueOf(pos + 1);
+ throw new InvalidResourceException("No name specified for resource parameter", paramNum);
+ }
+ name = constructorNames[pos];
+ } else if (pos < constructorNames.length && constructorNames[pos] != null
+ && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) {
+ String paramNum = String.valueOf(pos + 1);
+ throw new InvalidConstructorException("Name specified by @Constructor does not match resource name",
+ paramNum);
+ }
+ if (type.getResources().get(name) != null) {
+ throw new DuplicateResourceException(name);
+ }
+ org.apache.tuscany.spi.implementation.java.Resource<T> resource =
+ new org.apache.tuscany.spi.implementation.java.Resource<T>(name, param, null);
+ resource.setOptional(resourceAnnot.optional());
+ String mappedName = resourceAnnot.mappedName();
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.add(resource);
+ addName(explicitNames, pos, name);
+ }
+
+ protected static Class<?> getBaseType(Class<?> cls, Type genericType) {
+ if (cls.isArray()) {
+ return cls.getComponentType();
+ } else if (Collection.class.isAssignableFrom(cls)) {
+ if (genericType == cls) {
+ return Object.class;
+ } else {
+ ParameterizedType parameterizedType = (ParameterizedType) genericType;
+ Type baseType = parameterizedType.getActualTypeArguments()[0];
+ if (baseType instanceof Class) {
+ return (Class<?>) baseType;
+ } else if (baseType instanceof ParameterizedType) {
+ return (Class<?>) ((ParameterizedType) baseType).getRawType();
+ } else {
+ return null;
+ }
+ }
+ } else {
+ return cls;
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java
new file mode 100644
index 0000000000..d78632d496
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.processor;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.osoa.sca.annotations.Init;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Processes the {@link @Init} annotation on a component implementation and updates the component type with the
+ * decorated initializer method
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitProcessor extends ImplementationProcessorExtension {
+
+ public void visitMethod(Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ Init annotation = method.getAnnotation(Init.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 0) {
+ throw new IllegalInitException("Initializer must not have argments", method.toString());
+ }
+ if (type.getInitMethod() != null) {
+ throw new DuplicateInitException("More than one initializer found on implementaton");
+ }
+ if (Modifier.isProtected(method.getModifiers())) {
+ method.setAccessible(true);
+ }
+ type.setInitMethod(method);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java
new file mode 100644
index 0000000000..a2dd3f09c4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an invalid constructor definition, e.g. when the number of injection names specified in {@link
+ * org.osoa.sca.annotations.Constructor} do not match the number of actual constructor parameters
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidConstructorException extends ProcessingException {
+
+ public InvalidConstructorException(String message) {
+ super(message);
+ }
+
+ public InvalidConstructorException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java
new file mode 100644
index 0000000000..28bd65200e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java
@@ -0,0 +1,45 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Raised when an implementation specifies improper conversational metadata
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidConversationalImplementation extends ProcessingException {
+
+ public InvalidConversationalImplementation(String message) {
+ super(message);
+ }
+
+ public InvalidConversationalImplementation(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ public InvalidConversationalImplementation(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidConversationalImplementation(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java
new file mode 100644
index 0000000000..5d4c245764
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an invalid usage of {@link org.osoa.sca.annotations.Property}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidPropertyException extends ProcessingException {
+
+ public InvalidPropertyException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java
new file mode 100644
index 0000000000..8fbc07aa1c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an invalid usage of {@link org.osoa.sca.annotations.Reference}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidReferenceException extends ProcessingException {
+
+ public InvalidReferenceException(String message) {
+ super(message);
+ }
+
+ public InvalidReferenceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidReferenceException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java
new file mode 100644
index 0000000000..4ed6d93994
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Denotes an invalid usage of {@link @org.apache.tuscany.api.annotation.Resource}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidResourceException extends ProcessingException {
+
+ public InvalidResourceException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java
new file mode 100644
index 0000000000..f3d0367661
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when a service type specified by an {@link org.osoa.sca.annotations.Service} annotation is invalid, e.g. it is
+ * not an interface
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidServiceType extends ProcessingException {
+
+ public InvalidServiceType(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java
new file mode 100644
index 0000000000..f8d560504b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+
+import org.apache.tuscany.api.annotation.Monitor;
+import org.apache.tuscany.core.injection.SingletonObjectFactory;
+import org.apache.tuscany.host.MonitorFactory;
+
+/**
+ * Processes an {@link @Monitor} annotation, updating the component type with corresponding {@link
+ * org.apache.tuscany.spi.implementation.java.JavaMappedProperty}
+ *
+ * @version $Rev$ $Date$
+ */
+public class MonitorProcessor extends AbstractPropertyProcessor<Monitor> {
+ private MonitorFactory monitorFactory;
+
+ public MonitorProcessor(@Reference MonitorFactory factory, @Reference ImplementationProcessorService service) {
+ super(Monitor.class, service);
+ this.monitorFactory = factory;
+ }
+
+ protected String getName(Monitor annotation) {
+ return null;
+ }
+
+ protected <T> void initProperty(JavaMappedProperty<T> property,
+ Monitor annotation,
+ DeploymentContext context) {
+ Class<T> javaType = property.getJavaType();
+ property.setDefaultValueFactory(new SingletonObjectFactory<T>(monitorFactory.getMonitor(javaType)));
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java
new file mode 100644
index 0000000000..f36b7900a4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when a suitable constructor for a component implementation cannot be found
+ *
+ * @version $Rev$ $Date$
+ */
+public class NoConstructorException extends ProcessingException {
+
+ public NoConstructorException() {
+ }
+
+ public NoConstructorException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java
new file mode 100644
index 0000000000..206c937b05
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.reflect.Constructor;
+
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.model.TypeInfo;
+import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Processes an {@link @Property} annotation, updating the component type with corresponding {@link JavaMappedProperty}
+ *
+ * @version $Rev$ $Date$
+ */
+public class PropertyProcessor extends AbstractPropertyProcessor<Property> {
+ private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension();
+
+ public PropertyProcessor(@Reference ImplementationProcessorService service) {
+ super(Property.class, service);
+ }
+
+ protected String getName(Property annotation) {
+ return annotation.name();
+ }
+
+ protected <T> void initProperty(JavaMappedProperty<T> property,
+ Property annotation,
+ DeploymentContext context) {
+ property.setRequired(annotation.required());
+ TypeInfo type = typeMapper.getXMLType(property.getJavaType());
+ if (type != null) {
+ property.setXmlType(type.getQName());
+ }
+ }
+
+ public <T> void visitConstructor(Constructor<T> constructor,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ // override since heuristic pojo processor evalautes properties
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java
new file mode 100644
index 0000000000..9ecc1c768e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.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.core.implementation.processor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Collection;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName;
+
+/**
+ * Processes an {@link @Reference} annotation, updating the component type with corresponding {@link
+ * org.apache.tuscany.spi.implementation.java.JavaMappedReference}
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReferenceProcessor extends ImplementationProcessorExtension {
+
+ private JavaInterfaceProcessorRegistry regsitry;
+
+ public ReferenceProcessor(@Reference JavaInterfaceProcessorRegistry registry) {
+ this.regsitry = registry;
+ }
+
+ public void visitMethod(
+ Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ Reference annotation = method.getAnnotation(Reference.class);
+ if (annotation == null) {
+ return; // Not a reference annotation.
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalReferenceException("Setter must have one parameter", method.toString());
+ }
+ String name = null;
+ if (annotation.name() != null && annotation.name().length() > 0) {
+ name = annotation.name();
+ }
+ boolean required = annotation.required();
+ if (name == null) {
+ name = toPropertyName(method.getName());
+ }
+ if (type.getReferences().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+
+ JavaMappedReference reference = new JavaMappedReference();
+ reference.setMember(method);
+ reference.setRequired(required);
+ reference.setUri(URI.create("#" + name));
+ ServiceContract contract;
+ try {
+ Class<?> rawType = method.getParameterTypes()[0];
+ if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_N);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_N);
+ }
+ } else {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_ONE);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ }
+ }
+ Class<?> baseType = getBaseType(rawType, method.getGenericParameterTypes()[0]);
+ contract = regsitry.introspect(baseType);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ reference.setServiceContract(contract);
+ type.getReferences().put(name, reference);
+ }
+
+ public void visitField(
+ Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ Reference annotation = field.getAnnotation(Reference.class);
+ if (annotation == null) {
+ return;
+ }
+ String name = field.getName();
+ if (annotation.name() != null) {
+ name = annotation.name();
+ }
+ boolean required = annotation.required();
+ if (name.length() == 0) {
+ name = field.getName();
+ }
+ if (type.getReferences().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+ JavaMappedReference reference = new JavaMappedReference();
+ reference.setMember(field);
+ reference.setRequired(required);
+ reference.setUri(URI.create("#" + name));
+ ServiceContract contract;
+ try {
+ Class<?> rawType = field.getType();
+ if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_N);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_N);
+ }
+ } else {
+ if (required) {
+ reference.setMultiplicity(Multiplicity.ONE_ONE);
+ } else {
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ }
+ }
+ Class<?> baseType = getBaseType(rawType, field.getGenericType());
+ contract = regsitry.introspect(baseType);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ reference.setServiceContract(contract);
+ type.getReferences().put(name, reference);
+ }
+
+ public <T> void visitConstructor(
+ Constructor<T> constructor,
+ PojoComponentType<JavaMappedService,
+ JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java
new file mode 100644
index 0000000000..2db36652d0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java
@@ -0,0 +1,122 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.implementation.java.Resource;
+
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName;
+
+/**
+ * Processes an {@link @Resource} annotation, updating the component type with corresponding {@link
+ * org.apache.tuscany.spi.implementation.java.Resource}
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceProcessor extends ImplementationProcessorExtension {
+
+ public ResourceProcessor() {
+ }
+
+ public void visitMethod(
+ Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ org.apache.tuscany.api.annotation.Resource annotation =
+ method.getAnnotation(org.apache.tuscany.api.annotation.Resource.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalResourceException("Resource setter must have one parameter", method.toString());
+ }
+ Class<?> resourceType = method.getParameterTypes()[0];
+
+ String name = annotation.name();
+ if (name.length() < 1) {
+ name = toPropertyName(method.getName());
+ }
+ if (type.getResources().get(name) != null) {
+ throw new DuplicateResourceException(name);
+ }
+
+ String mappedName = annotation.mappedName();
+ Resource<?> resource = createResource(name, resourceType, method);
+ resource.setOptional(annotation.optional());
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.add(resource);
+ }
+
+ public void visitField(
+ Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ org.apache.tuscany.api.annotation.Resource annotation =
+ field.getAnnotation(org.apache.tuscany.api.annotation.Resource.class);
+ if (annotation == null) {
+ return;
+ }
+ String name = annotation.name();
+ if (name.length() < 1) {
+ name = field.getName();
+ }
+ if (type.getResources().get(name) != null) {
+ throw new DuplicateResourceException(name);
+ }
+
+ Class<?> fieldType = field.getType();
+ String mappedName = annotation.mappedName();
+
+ Resource<?> resource = createResource(name, fieldType, field);
+ resource.setOptional(annotation.optional());
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.add(resource);
+ }
+
+ public <T> Resource<T> createResource(String name, Class<T> type, Member member) {
+ return new Resource<T>(name, type, member);
+ }
+
+ public <T> void visitConstructor(
+ Constructor<T> constructor,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java
new file mode 100644
index 0000000000..efd0e25cd3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.model.Scope;
+
+/**
+ * Processes the {@link Scope} annotation and updates the component type with the corresponding implmentation scope
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeProcessor extends ImplementationProcessorExtension {
+
+ public <T> void visitClass(Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ org.osoa.sca.annotations.Scope annotation = clazz.getAnnotation(org.osoa.sca.annotations.Scope.class);
+ if (annotation == null) {
+ type.setImplementationScope(Scope.STATELESS);
+ return;
+ }
+ String name = annotation.value();
+ Scope scope;
+ if ("COMPOSITE".equals(name)) {
+ scope = Scope.COMPOSITE;
+ } else if ("SESSION".equals(name)) {
+ scope = Scope.SESSION;
+ } else if ("CONVERSATION".equals(name)) {
+ scope = Scope.CONVERSATION;
+ } else if ("REQUEST".equals(name)) {
+ scope = Scope.REQUEST;
+ } else if ("SYSTEM".equals(name)) {
+ scope = Scope.SYSTEM;
+ } else {
+ scope = new Scope(name);
+ }
+ type.setImplementationScope(scope);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java
new file mode 100644
index 0000000000..8d6e72cae3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java
@@ -0,0 +1,155 @@
+/*
+ * 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.core.implementation.processor;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllInterfaces;
+import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName;
+
+/**
+ * Processes an {@link org.osoa.sca.annotations.Service} annotation and updates the component type with corresponding
+ * {@link JavaMappedService}s. Also processes related {@link org.osoa.sca.annotations.Callback} annotations.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceProcessor extends ImplementationProcessorExtension {
+
+ private ImplementationProcessorService implService;
+
+ public ServiceProcessor(@Reference ImplementationProcessorService implService) {
+ this.implService = implService;
+ }
+
+ public <T> void visitClass(Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ org.osoa.sca.annotations.Service annotation = clazz.getAnnotation(org.osoa.sca.annotations.Service.class);
+ if (annotation == null) {
+ // scan intefaces for remotable
+ Set<Class> interfaces = getAllInterfaces(clazz);
+ for (Class<?> interfaze : interfaces) {
+ if (interfaze.isAnnotationPresent(Remotable.class) || interfaze.isAnnotationPresent(Callback.class)) {
+ JavaMappedService service;
+ try {
+ service = implService.createService(interfaze);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getServices().put(service.getUri().getFragment(), service);
+ }
+ }
+ return;
+ }
+ Class<?>[] interfaces = annotation.interfaces();
+ if (interfaces.length == 0) {
+ Class<?> interfaze = annotation.value();
+ if (Void.class.equals(interfaze)) {
+ throw new IllegalServiceDefinitionException("No interfaces specified");
+ } else {
+ interfaces = new Class<?>[1];
+ interfaces[0] = interfaze;
+ }
+ }
+ for (Class<?> interfaze : interfaces) {
+ if (!interfaze.isInterface()) {
+ throw new InvalidServiceType("Service must be an interface", interfaze.getName());
+ }
+ JavaMappedService service;
+ try {
+ service = implService.createService(interfaze);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getServices().put(service.getUri().getFragment(), service);
+ }
+ }
+
+
+ public void visitMethod(
+ Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ Callback annotation = method.getAnnotation(Callback.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalCallbackReferenceException("Setter must have one parameter", method.toString());
+ }
+ String name = toPropertyName(method.getName());
+ JavaMappedService callbackService = null;
+ Class<?> callbackClass = method.getParameterTypes()[0];
+ for (JavaMappedService service : type.getServices().values()) {
+ ServiceContract serviceContract = service.getServiceContract();
+ if (serviceContract.getCallbackClass().equals(callbackClass)) {
+ callbackService = service;
+ }
+ }
+ if (callbackService == null) {
+ throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface");
+ }
+ callbackService.setCallbackReferenceName(name);
+ callbackService.setCallbackMember(method);
+ }
+
+ public void visitField(Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ Callback annotation = field.getAnnotation(Callback.class);
+ if (annotation == null) {
+ return;
+ }
+ String name = field.getName();
+ JavaMappedService callbacksService = null;
+ Class<?> callbackClass = field.getType();
+ for (JavaMappedService service : type.getServices().values()) {
+ ServiceContract serviceContract = service.getServiceContract();
+ if (serviceContract.getCallbackClass().equals(callbackClass)) {
+ callbacksService = service;
+ }
+ }
+ if (callbacksService == null) {
+ throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface");
+ }
+ callbacksService.setCallbackReferenceName(name);
+ callbacksService.setCallbackMember(field);
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java
new file mode 100644
index 0000000000..8a0d4afc3d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.implementation.processor;
+
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+
+/**
+ * Thrown when a service interface cannot be determined based on a heuristic evaluation of an implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceTypeNotFoundException extends ProcessingException {
+
+ public ServiceTypeNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java
new file mode 100644
index 0000000000..a7868349a6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.processor;
+
+/**
+ * Thrown when a method or field marked with {@link org.osoa.sca.annotations.Context} takes an unknown type
+ *
+ * @version $Rev$ $Date$
+ */
+public class UnknownContextTypeException extends IllegalContextException {
+
+ public UnknownContextTypeException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java
new file mode 100644
index 0000000000..369ac13ca4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java
@@ -0,0 +1,160 @@
+/*
+ * 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.core.implementation.system.builder;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.builder.BuilderConfigException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentBuilderExtension;
+import org.apache.tuscany.spi.host.ResourceHost;
+import org.apache.tuscany.spi.implementation.java.ConstructorDefinition;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.Resource;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.PropertyValue;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+import org.apache.tuscany.core.implementation.PojoConfiguration;
+import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl;
+import org.apache.tuscany.core.implementation.system.model.SystemImplementation;
+import org.apache.tuscany.core.injection.MethodEventInvoker;
+import org.apache.tuscany.core.injection.PojoObjectFactory;
+import org.apache.tuscany.core.injection.ResourceObjectFactory;
+
+/**
+ * Produces system atomic components from a component definition
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SystemComponentBuilder extends ComponentBuilderExtension<SystemImplementation> {
+ private ResourceHost host;
+
+ protected Class<SystemImplementation> getImplementationType() {
+ return SystemImplementation.class;
+ }
+
+ @Reference
+ public void setHost(ResourceHost host) {
+ this.host = host;
+ }
+
+ @SuppressWarnings("unchecked")
+ public AtomicComponent build(ComponentDefinition<SystemImplementation> definition, DeploymentContext context)
+ throws BuilderConfigException {
+
+ PojoComponentType<ServiceDefinition, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ definition.getImplementation().getComponentType();
+
+ PojoConfiguration configuration = new PojoConfiguration();
+ if (definition.getInitLevel() != null) {
+ configuration.setInitLevel(definition.getInitLevel());
+ } else {
+ configuration.setInitLevel(componentType.getInitLevel());
+ }
+ Method initMethod = componentType.getInitMethod();
+ if (initMethod != null) {
+ configuration.setInitInvoker(new MethodEventInvoker<Object>(initMethod));
+ }
+ Method destroyMethod = componentType.getDestroyMethod();
+ if (destroyMethod != null) {
+ configuration.setDestroyInvoker(new MethodEventInvoker<Object>(destroyMethod));
+ }
+ // setup property injection sites
+ for (JavaMappedProperty<?> property : componentType.getProperties().values()) {
+ configuration.addPropertySite(property.getName(), property.getMember());
+ }
+ // setup reference injection sites
+ for (JavaMappedReference reference : componentType.getReferences().values()) {
+ Member member = reference.getMember();
+ if (member != null) {
+ // could be null if the reference is mapped to a constructor
+ configuration.addReferenceSite(reference.getUri().getFragment(), member);
+ }
+ }
+
+ for (Resource resource : componentType.getResources().values()) {
+ Member member = resource.getMember();
+ if (member != null) {
+ // could be null if the resource is mapped to a constructor
+ configuration.addResourceSite(resource.getName(), member);
+ }
+ }
+
+ // setup constructor injection
+ ConstructorDefinition<?> ctorDef = componentType.getConstructorDefinition();
+ Constructor<?> constr = ctorDef.getConstructor();
+ PojoObjectFactory<?> instanceFactory = new PojoObjectFactory(constr);
+ configuration.setInstanceFactory(instanceFactory);
+ configuration.getConstructorParamNames().addAll(ctorDef.getInjectionNames());
+ for (Class<?> clazz : constr.getParameterTypes()) {
+ configuration.addConstructorParamType(clazz);
+ }
+ configuration.setName(definition.getUri());
+ SystemAtomicComponentImpl component = new SystemAtomicComponentImpl(configuration);
+ // handle properties
+ Map<String, PropertyValue<?>> propertyValues = definition.getPropertyValues();
+ processProperties(propertyValues, componentType.getProperties().values(), component);
+
+ // handle resources
+ for (Resource resource : componentType.getResources().values()) {
+ String name = resource.getName();
+ boolean optional = resource.isOptional();
+ Class<Object> type = (Class<Object>) resource.getType();
+ ResourceObjectFactory<Object> factory;
+ String mappedName = resource.getMappedName();
+ if (mappedName == null) {
+ // by type
+ factory = new ResourceObjectFactory<Object>(type, optional, host);
+ } else {
+ factory = new ResourceObjectFactory<Object>(type, mappedName, optional, host);
+ }
+ component.addResourceFactory(name, factory);
+
+ }
+ return component;
+ }
+
+ private void processProperties(Map<String, PropertyValue<?>> propertyValues,
+ Collection<JavaMappedProperty<?>> properties,
+ SystemAtomicComponentImpl component) {
+ for (JavaMappedProperty<?> property : properties) {
+ PropertyValue value = propertyValues.get(property.getName());
+ ObjectFactory<?> factory;
+ if (value != null) {
+ factory = value.getValueFactory();
+ } else {
+ factory = property.getDefaultValueFactory();
+ }
+ if (factory != null) {
+ component.addPropertyFactory(property.getName(), factory);
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java
new file mode 100644
index 0000000000..f15dd2aa9d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.implementation.system.component;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+
+import org.apache.tuscany.core.implementation.PojoAtomicComponent;
+import org.apache.tuscany.core.implementation.PojoConfiguration;
+import org.apache.tuscany.core.wire.OptimizedWireObjectFactory;
+
+/**
+ * Default implementation of a system atomic context
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SystemAtomicComponentImpl extends PojoAtomicComponent {
+
+ public SystemAtomicComponentImpl(PojoConfiguration configuration) {
+ super(configuration);
+ scope = Scope.COMPOSITE;
+ }
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation) {
+ return null;
+ }
+
+ protected <B> ObjectFactory<B> createWireFactory(Class<B> interfaze, Wire wire) {
+ return new OptimizedWireObjectFactory<B>(interfaze, wire);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java
new file mode 100644
index 0000000000..05fbd42e22
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.implementation.system.loader;
+
+import java.net.URL;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension;
+import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry;
+import org.apache.tuscany.spi.implementation.java.Introspector;
+import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
+import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
+import org.apache.tuscany.spi.implementation.java.JavaMappedService;
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.implementation.java.ProcessingException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.Scope;
+
+import org.apache.tuscany.core.implementation.system.model.SystemImplementation;
+import org.apache.tuscany.core.util.JavaIntrospectionHelper;
+
+/**
+ * Loads a system component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemComponentTypeLoader extends ComponentTypeLoaderExtension<SystemImplementation> {
+ private Introspector introspector;
+
+ public SystemComponentTypeLoader() {
+ }
+
+ public SystemComponentTypeLoader(Introspector introspector) {
+ this.introspector = introspector;
+ }
+
+ public SystemComponentTypeLoader(LoaderRegistry loaderRegistry, Introspector introspector) {
+ super(loaderRegistry);
+ this.introspector = introspector;
+ }
+
+ @Reference
+ public void setIntrospector(IntrospectionRegistry introspector) {
+ this.introspector = introspector;
+ }
+
+ public void load(
+ SystemImplementation implementation,
+ DeploymentContext deploymentContext) throws LoaderException {
+ Class<?> implClass = implementation.getImplementationClass();
+ URL sidefile = implClass.getResource(JavaIntrospectionHelper.getBaseName(implClass) + ".componentType");
+ PojoComponentType componentType;
+ if (sidefile == null) {
+ componentType = loadByIntrospection(implementation, deploymentContext);
+ } else {
+ componentType = loadFromSidefile(sidefile, deploymentContext);
+ }
+ // this means system components are always composite scoped
+ componentType.setImplementationScope(Scope.COMPOSITE);
+ implementation.setComponentType(componentType);
+ }
+
+ protected Class<SystemImplementation> getImplementationClass() {
+ return SystemImplementation.class;
+ }
+
+ protected PojoComponentType loadByIntrospection(SystemImplementation implementation, DeploymentContext context)
+ throws ProcessingException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>();
+ Class<?> implClass = implementation.getImplementationClass();
+ introspector.introspect(implClass, componentType, context);
+ return componentType;
+ }
+
+
+ protected PojoComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException {
+ return loaderRegistry.load(null, url, PojoComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java
new file mode 100644
index 0000000000..7a6e1b5c83
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.implementation.system.loader;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+
+import org.apache.tuscany.core.deployer.ChildDeploymentContext;
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+
+/**
+ * Loads a system composite component type
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemCompositeComponentTypeLoader extends ComponentTypeLoaderExtension<SystemCompositeImplementation> {
+ public SystemCompositeComponentTypeLoader() {
+ }
+
+ public SystemCompositeComponentTypeLoader(LoaderRegistry loaderRegistry) {
+ super(loaderRegistry);
+ }
+
+ protected Class<SystemCompositeImplementation> getImplementationClass() {
+ return SystemCompositeImplementation.class;
+ }
+
+ public void load(
+ SystemCompositeImplementation implementation,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ URL scdlLocation = implementation.getScdlLocation();
+ if (scdlLocation == null) {
+ throw new LoaderException("SCDL location not found");
+ }
+ ClassLoader cl = implementation.getClassLoader();
+ URI componentId = deploymentContext.getComponentId();
+ DeploymentContext childContext = new ChildDeploymentContext(deploymentContext,
+ cl,
+ scdlLocation,
+ componentId,
+ deploymentContext.isAutowire());
+ CompositeComponentType componentType = loadFromSidefile(scdlLocation, childContext);
+ implementation.setComponentType(componentType);
+ }
+
+
+ protected CompositeComponentType loadFromSidefile(URL url, DeploymentContext context) throws LoaderException {
+ return loaderRegistry.load(null, url, CompositeComponentType.class, context);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java
new file mode 100644
index 0000000000..f2dd88bfcc
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.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.core.implementation.system.loader;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.ModelObject;
+
+import org.apache.tuscany.core.implementation.system.model.SystemImplementation;
+
+/**
+ * Loads information for a system implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemImplementationLoader extends LoaderExtension<SystemImplementation> {
+ public static final QName SYSTEM_IMPLEMENTATION =
+ new QName("http://tuscany.apache.org/xmlns/sca/system/2.0-alpha", "implementation.system");
+
+ public SystemImplementationLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public SystemImplementation load(
+ ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+ assert SYSTEM_IMPLEMENTATION.equals(reader.getName());
+ SystemImplementation implementation = new SystemImplementation();
+ String implClass = reader.getAttributeValue(null, "class");
+ Class<?> implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader());
+ implementation.setImplementationClass(implementationClass);
+ registry.loadComponentType(implementation, deploymentContext);
+ while (true) {
+ int code = reader.next();
+ if (code == XMLStreamConstants.START_ELEMENT) {
+ throw new UnrecognizedElementException(reader.getName());
+ } else if (code == XMLStreamConstants.END_ELEMENT) {
+ return implementation;
+ }
+ }
+ }
+
+ public QName getXMLType() {
+ return SYSTEM_IMPLEMENTATION;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java
new file mode 100644
index 0000000000..e634609c5b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java
@@ -0,0 +1,57 @@
+/*
+ * 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.core.implementation.system.model;
+
+import java.net.URL;
+
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+
+/**
+ * Represents a system composite type
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemCompositeImplementation extends Implementation<CompositeComponentType> {
+ private URL scdlLocation;
+ private ClassLoader classLoader;
+
+ public SystemCompositeImplementation() {
+ }
+
+ public SystemCompositeImplementation(CompositeComponentType componentType) {
+ super(componentType);
+ }
+
+ public URL getScdlLocation() {
+ return scdlLocation;
+ }
+
+ public void setScdlLocation(URL scdlLocation) {
+ this.scdlLocation = scdlLocation;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java
new file mode 100644
index 0000000000..ce48ed3fe5
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java
@@ -0,0 +1,51 @@
+/*
+ * 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.core.implementation.system.model;
+
+import org.apache.tuscany.spi.implementation.java.PojoComponentType;
+import org.apache.tuscany.spi.model.AtomicImplementation;
+
+/**
+ * Represents the system composite implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemImplementation extends AtomicImplementation<PojoComponentType> {
+ private Class<?> implementationClass;
+
+ public SystemImplementation(PojoComponentType componentType, Class<?> implementationClass) {
+ super(componentType);
+ this.implementationClass = implementationClass;
+ }
+
+ public SystemImplementation() {
+ }
+
+ public SystemImplementation(Class<?> implementationClass) {
+ this.implementationClass = implementationClass;
+ }
+
+ public Class<?> getImplementationClass() {
+ return implementationClass;
+ }
+
+ public void setImplementationClass(Class<?> implementationClass) {
+ this.implementationClass = implementationClass;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java
new file mode 100644
index 0000000000..1a441dcf87
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.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.core.injection;
+
+import java.lang.reflect.Array;
+import java.util.List;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Resolves targets configured in a multiplicity by delegating to object factories and returning an <code>Array</code>
+ * containing object instances
+ *
+ * @version $Rev$ $Date$
+ */
+public class ArrayMultiplicityObjectFactory implements ObjectFactory<Object> {
+
+ private ObjectFactory[] factories;
+
+ private Class interfaceType;
+
+ public ArrayMultiplicityObjectFactory(Class interfaceType, List<ObjectFactory<?>> factories) {
+ assert interfaceType != null : "Interface type was null";
+ assert factories != null : "Object factories were null";
+ this.interfaceType = interfaceType;
+ this.factories = factories.toArray(new ObjectFactory[factories.size()]);
+ }
+
+ public Object getInstance() throws ObjectCreationException {
+ Object array = Array.newInstance(interfaceType, factories.length);
+ for (int i = 0; i < factories.length; i++) {
+ Array.set(array, i, factories[i].getInstance());
+ }
+ return array;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java
new file mode 100644
index 0000000000..519397e9ff
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.injection;
+
+import java.util.List;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.ProxyService;
+
+/**
+ * Returns proxy instance for a wire callback
+ *
+ * @version $Rev$ $Date$
+ */
+public class CallbackWireObjectFactory implements ObjectFactory {
+ private ProxyService proxyService;
+ private Class<?> interfaze;
+ private List<Wire> wires;
+
+ public CallbackWireObjectFactory(Class<?> interfaze, ProxyService proxyService, List<Wire> wires) {
+ this.interfaze = interfaze;
+ this.proxyService = proxyService;
+ this.wires = wires;
+ }
+
+ public Object getInstance() throws ObjectCreationException {
+ return proxyService.createCallbackProxy(interfaze, wires);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java
new file mode 100644
index 0000000000..a422500f3c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.injection;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+
+/**
+ * Implementations inject a pre-configured context type (interface) on an instance.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContextInjector<S, T> extends Injector<T> {
+
+ void setContext(S context) throws ObjectCreationException;
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java
new file mode 100644
index 0000000000..8dbc0a3a83
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.injection;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Scope;
+
+public class ConversationIDObjectFactory implements ObjectFactory<String> {
+
+ private WorkContext workContext;
+
+ public ConversationIDObjectFactory(WorkContext workContext) {
+ this.workContext = workContext;
+ }
+
+ public String getInstance() {
+ return (String)workContext.getIdentifier(Scope.CONVERSATION);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java
new file mode 100644
index 0000000000..af2382b36a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.injection;
+
+/**
+ * Performs an invocation on an instance
+ *
+ * @version $Rev$ $Date$
+ */
+public interface EventInvoker<T> {
+
+ /**
+ * Performs the invocation on a given instance
+ *
+ * @throws ObjectCallbackException
+ */
+ void invokeEvent(T instance) throws ObjectCallbackException;
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java
new file mode 100644
index 0000000000..e9f8f42aa1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java
@@ -0,0 +1,57 @@
+/*
+ * 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.core.injection;
+
+import java.lang.reflect.Field;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Injects a value created by an {@link org.apache.tuscany.spi.ObjectFactory} on a given field
+ *
+ * @version $Rev$ $Date$
+ */
+public class FieldInjector<T> implements Injector<T> {
+
+ private final Field field;
+
+ private final ObjectFactory<?> objectFactory;
+
+ /**
+ * Create an injector and have it use the given <code>ObjectFactory</code> to inject a value on the instance using
+ * the reflected <code>Field</code>
+ */
+ public FieldInjector(Field field, ObjectFactory<?> objectFactory) {
+ this.field = field;
+ this.field.setAccessible(true);
+ this.objectFactory = objectFactory;
+ }
+
+ /**
+ * Inject a new value on the given isntance
+ */
+ public void inject(T instance) throws ObjectCreationException {
+ try {
+ field.set(instance, objectFactory.getInstance());
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Field is not accessible [" + field + "]");
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java
new file mode 100644
index 0000000000..c5f037d931
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.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.core.injection;
+
+import org.apache.tuscany.api.TuscanyRuntimeException;
+
+/**
+ * Root unchecked exception for the injection package
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class InjectionRuntimeException extends TuscanyRuntimeException {
+
+ public InjectionRuntimeException() {
+ super();
+ }
+
+ public InjectionRuntimeException(String message) {
+ super(message);
+ }
+
+
+ protected InjectionRuntimeException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ public InjectionRuntimeException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected InjectionRuntimeException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+
+ public InjectionRuntimeException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/Injector.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/Injector.java
new file mode 100644
index 0000000000..c2125d8212
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/Injector.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.injection;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+
+/**
+ * Implementations inject a pre-configured value on an instance
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Injector<T> {
+
+ /**
+ * Inject a value on the given instance
+ */
+ void inject(T instance) throws ObjectCreationException;
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java
new file mode 100644
index 0000000000..2e7ff0e754
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.injection;
+
+/**
+ * @version $$Rev$$ $$Date$$
+ */
+public class InvalidAccessorException extends InjectionRuntimeException {
+
+ public InvalidAccessorException(String message) {
+ super(message);
+ }
+
+ public InvalidAccessorException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java
new file mode 100644
index 0000000000..1a3eaf4d1a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.core.injection;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+
+/**
+ * Denotes an invalid resource type, i.e. that is not a component
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidResourceTypeException extends ObjectCreationException {
+
+ public InvalidResourceTypeException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java
new file mode 100644
index 0000000000..0189d8245b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.injection;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * An implementation of ObjectFactory that creates instances by looking them up in a JNDI context.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JNDIObjectFactory<T> implements ObjectFactory<T> {
+ private final Context context;
+ private final String name;
+
+ public JNDIObjectFactory(Context context, String name) {
+ this.context = context;
+ this.name = name;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public T getInstance() throws ObjectCreationException {
+ try {
+ return (T) context.lookup(name);
+ } catch (NamingException e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java
new file mode 100644
index 0000000000..b261bcda53
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.injection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Resolves targets configured in a multiplicity by delegating to object factories and returning an <code>List</code>
+ * containing object instances
+ *
+ * @version $Rev$ $Date$
+ */
+public class ListMultiplicityObjectFactory implements ObjectFactory<List> {
+
+ private ObjectFactory[] factories;
+
+ public ListMultiplicityObjectFactory(List<ObjectFactory<?>> factories) {
+ assert factories != null : "Object factories were null";
+ this.factories = factories.toArray(new ObjectFactory[factories.size()]);
+ }
+
+ public List getInstance() throws ObjectCreationException {
+ List<Object> list = new ArrayList<Object>();
+ for (ObjectFactory factory : factories) {
+ list.add(factory.getInstance());
+ }
+ return list;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java
new file mode 100644
index 0000000000..e43a1e1fa6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.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.core.injection;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Performs an wire on a method of a given instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class MethodEventInvoker<T> implements EventInvoker<T> {
+ private final Method method;
+
+ /**
+ * Intantiates an invoker for the given method
+ */
+ public MethodEventInvoker(Method method) {
+ assert method != null;
+ this.method = method;
+ }
+
+ public void invokeEvent(T instance) throws ObjectCallbackException {
+ try {
+ method.invoke(instance, (Object[]) null);
+ } catch (IllegalArgumentException e) {
+ String name = method.getName();
+ throw new ObjectCallbackException("Exception thrown by callback method [" + name + "]", e.getCause());
+ } catch (IllegalAccessException e) {
+ String name = method.getName();
+ throw new AssertionError("Method is not accessible [" + name + "]");
+ } catch (InvocationTargetException e) {
+ String name = method.getName();
+ throw new ObjectCallbackException("Exception thrown by callback method [" + name + "]", e.getCause());
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java
new file mode 100644
index 0000000000..258f0817dd
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.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.core.injection;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Injects a value created by an {@link org.apache.tuscany.spi.ObjectFactory} using a given method
+ *
+ * @version $Rev$ $Date$
+ */
+public class MethodInjector<T> implements Injector<T> {
+ private final Method method;
+ private final ObjectFactory<?> objectFactory;
+
+ public MethodInjector(Method method, ObjectFactory<?> objectFactory) {
+ assert method != null;
+ assert objectFactory != null;
+ this.method = method;
+ this.method.setAccessible(true);
+ this.objectFactory = objectFactory;
+ }
+
+ public void inject(T instance) throws ObjectCreationException {
+ try {
+ method.invoke(instance, objectFactory.getInstance());
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("Method is not accessible [" + method + "]");
+ } catch (IllegalArgumentException e) {
+ throw new ObjectCreationException("Exception thrown by setter", method.getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new ObjectCreationException("Exception thrown by setter", method.getName(), e);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java
new file mode 100644
index 0000000000..b3109074e3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.injection;
+
+/**
+ * @version $$Rev$$ $$Date$$
+ */
+public class NoAccessorException extends InjectionRuntimeException {
+ public NoAccessorException() {
+ }
+
+ public NoAccessorException(String message) {
+ super(message);
+ }
+
+ public NoAccessorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public NoAccessorException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java
new file mode 100644
index 0000000000..a86451525b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.core.injection;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class NoMultiplicityTypeException extends InjectionRuntimeException {
+
+ public NoMultiplicityTypeException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java
new file mode 100644
index 0000000000..ff830aab4b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.injection;
+
+/**
+ * Denotes an error when invoking on an object
+ *
+ * @version $Rev$ $Date$
+ */
+public class ObjectCallbackException extends InjectionRuntimeException {
+
+ public ObjectCallbackException() {
+ super();
+ }
+
+ public ObjectCallbackException(String message) {
+ super(message);
+ }
+
+ public ObjectCallbackException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ public ObjectCallbackException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ObjectCallbackException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java
new file mode 100644
index 0000000000..d36af74de5
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java
@@ -0,0 +1,120 @@
+/*
+ * 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.core.injection;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Creates new instances of a Java class
+ *
+ * @version $Rev$ $Date$
+ * @see org.apache.tuscany.core.injection.Injector
+ */
+public class PojoObjectFactory<T> implements ObjectFactory<T> {
+
+ private final Constructor<T> ctr;
+ private ObjectFactory[] initializerFactories;
+
+ /**
+ * Creates the object factory
+ *
+ * @param ctr the constructor to use when instantiating a new object
+ */
+ public PojoObjectFactory(Constructor<T> ctr) {
+ assert ctr != null;
+ this.ctr = ctr;
+ initializerFactories = new ObjectFactory[ctr.getParameterTypes().length];
+ }
+
+ /**
+ * Creates the object factory
+ *
+ * @param ctr the constructor to use when instantiating a new object
+ * @param factories an ordered list of <code>ObjectFactory</code>s to use for returning constructor parameters
+ */
+ public PojoObjectFactory(Constructor<T> ctr, List<ObjectFactory> factories) {
+ assert ctr != null;
+ int params = ctr.getParameterTypes().length;
+ assert params == factories.size();
+ this.ctr = ctr;
+ initializerFactories = new ObjectFactory[params];
+ int i = 0;
+ for (ObjectFactory factory : factories) {
+ initializerFactories[i] = factory;
+ i++;
+ }
+ }
+
+ /**
+ * Returns the ordered array of <code>ObjectFactory</code>s use in creating constructor parameters
+ */
+ public ObjectFactory[] getInitializerFactories() {
+ return initializerFactories;
+ }
+
+ /**
+ * Sets an <code>ObjectFactory</code>s to use in creating constructor parameter
+ *
+ * @param pos the constructor parameter position
+ * @param factory the object factory
+ */
+ public void setInitializerFactory(int pos, ObjectFactory factory) {
+ assert pos < initializerFactories.length;
+ initializerFactories[pos] = factory;
+ }
+
+ /**
+ * Creates a new instance of an object
+ */
+ public T getInstance() throws ObjectCreationException {
+ int size = initializerFactories.length;
+ Object[] initargs = new Object[size];
+ // create the constructor arg array
+ for (int i = 0; i < size; i++) {
+ ObjectFactory<?> objectFactory = initializerFactories[i];
+ if (objectFactory == null) {
+ // this can happen if a reference is optional
+ initargs[i] = null;
+ } else {
+ initargs[i] = objectFactory.getInstance();
+ }
+ }
+ try {
+ ctr.setAccessible(true);
+ return ctr.newInstance(initargs);
+ } catch (IllegalArgumentException e) {
+ String name = ctr.getName();
+ throw new ObjectCreationException("Exception thrown by constructor", name, e);
+ } catch (InstantiationException e) {
+ String name = ctr.getDeclaringClass().getName();
+ throw new AssertionError("Class is not instantiable [" + name + "]");
+ } catch (IllegalAccessException e) {
+ String name = ctr.getName();
+ throw new AssertionError("Constructor is not accessible [" + name + "]");
+ } catch (InvocationTargetException e) {
+ String name = ctr.getName();
+ throw new ObjectCreationException("Exception thrown by constructor", name, e);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java
new file mode 100644
index 0000000000..92a422a968
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.injection;
+
+import org.osoa.sca.RequestContext;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.WorkContext;
+
+import org.apache.tuscany.core.implementation.composite.ManagedRequestContext;
+
+/**
+ * Creates instances of {@link org.apache.tuscany.core.implementation.composite.ManagedRequestContext} for injection on
+ * component implementation instances
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestContextObjectFactory implements ObjectFactory<RequestContext> {
+ private WorkContext workContext;
+
+ public RequestContextObjectFactory(WorkContext workContext) {
+ assert workContext != null;
+ this.workContext = workContext;
+ }
+
+ public ManagedRequestContext getInstance() throws ObjectCreationException {
+ return new ManagedRequestContext(workContext);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java
new file mode 100644
index 0000000000..ed3ac20631
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.injection;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+
+/**
+ * Denotes an exception thrown when a runtime resource is not found
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceNotFoundException extends ObjectCreationException {
+
+ public ResourceNotFoundException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java
new file mode 100644
index 0000000000..bb2f335506
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java
@@ -0,0 +1,89 @@
+/*
+ * 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.core.injection;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.host.ResourceHost;
+import org.apache.tuscany.spi.host.ResourceResolutionException;
+
+/**
+ * Resolves a runtime resource to be injected on a field or method of a Java component type marked with {@link
+ * org.apache.tuscany.api.annotation.Resource}. If the mapped name of the resource is an absolute URI such as
+ * <code>sca://localhost</code> or <code>jndi://localhost</code> the host container namespace is searched; otherwise the
+ * URI is assumed to be relative and the parent composite is searched. If a mapped name is not provided, i.e. resolution
+ * is by type, the parent composite is first searched followed by the host namespace.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceObjectFactory<T> implements ObjectFactory<T> {
+
+ private Class<T> type;
+ private String mappedName;
+ private ResourceHost host;
+ private boolean optional;
+
+ /**
+ * Instantiates a factory that resolves resources by type
+ *
+ * @param type the type of the resource to inject
+ * @param optional true if an error should be thrown if the resource is not found
+ * @param host the runtime resource provider
+ */
+ public ResourceObjectFactory(Class<T> type, boolean optional, ResourceHost host) {
+ this(type, null, optional, host);
+ }
+
+ /**
+ * Instantiates a factory that resolves resources by mapped name
+ *
+ * @param type the type of the resource to inject
+ * @param mappedName the resource name
+ * @param optional true if an error should be thrown if the resource is not found
+ * @param host the runtime resource provider
+ */
+ public ResourceObjectFactory(Class<T> type, String mappedName, boolean optional, ResourceHost host) {
+ this.type = type;
+ this.host = host;
+ this.mappedName = mappedName;
+ this.optional = optional;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public T getInstance() throws ObjectCreationException {
+ try {
+ T resource;
+ if (mappedName == null) {
+ resource = host.resolveResource(type);
+ if (!optional && resource == null) {
+ throw new ResourceNotFoundException("Resource not found", type.getName());
+ }
+ } else {
+ resource = host.resolveResource(type, mappedName);
+ if (!optional && resource == null) {
+ throw new ResourceNotFoundException("Resource not found", mappedName);
+ }
+ }
+ return resource;
+ } catch (ResourceResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java
new file mode 100644
index 0000000000..713c1ae54f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java
@@ -0,0 +1,39 @@
+/*
+ * 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.core.injection;
+
+import org.apache.tuscany.spi.ObjectFactory;
+
+/**
+ * Implementation of ObjectFactory that returns a single instance, typically an immutable type.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SingletonObjectFactory<T> implements ObjectFactory<T> {
+ private final T instance;
+
+ public SingletonObjectFactory(T instance) {
+ this.instance = instance;
+ }
+
+ public T getInstance() {
+ return instance;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java
new file mode 100644
index 0000000000..8656890ad9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java
@@ -0,0 +1,348 @@
+/*
+ * 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.core.loader;
+
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.w3c.dom.Document;
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidReferenceException;
+import org.apache.tuscany.spi.loader.InvalidValueException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.MissingImplementationException;
+import org.apache.tuscany.spi.loader.MissingReferenceException;
+import org.apache.tuscany.spi.loader.MissingRequiredPropertyException;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+import org.apache.tuscany.spi.loader.ReferenceMultiplicityViolationException;
+import org.apache.tuscany.spi.loader.UndefinedPropertyException;
+import org.apache.tuscany.spi.loader.UndefinedReferenceException;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ReferenceTarget;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+import org.apache.tuscany.core.binding.local.LocalBindingDefinition;
+import org.apache.tuscany.core.deployer.ChildDeploymentContext;
+import org.apache.tuscany.core.property.SimplePropertyObjectFactory;
+
+/**
+ * Loads a component definition from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class ComponentLoader extends LoaderExtension<ComponentDefinition<?>> {
+ private static final QName COMPONENT = new QName(SCA_NS, "component");
+ private static final QName PROPERTY = new QName(SCA_NS, "property");
+ private static final QName REFERENCE = new QName(SCA_NS, "reference");
+
+ private static final String PROPERTY_FILE_ATTR = "file";
+ private static final String PROPERTY_NAME_ATTR = "name";
+ private static final String PROPERTY_SOURCE_ATTR = "source";
+
+ private PropertyObjectFactory propertyFactory;
+
+ @Constructor
+ public ComponentLoader(@Reference LoaderRegistry registry, @Reference PropertyObjectFactory propertyFactory) {
+ super(registry);
+ this.propertyFactory = propertyFactory;
+ }
+
+ public QName getXMLType() {
+ return COMPONENT;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ComponentDefinition<?> load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert COMPONENT.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String initLevel = reader.getAttributeValue(null, "initLevel");
+ String autowireAttr = reader.getAttributeValue(null, "autowire");
+ boolean autowire;
+ if (autowireAttr == null) {
+ autowire = context.isAutowire();
+ } else {
+ autowire = Boolean.parseBoolean(autowireAttr);
+ }
+
+ URI componentId = URI.create(context.getComponentId() + "/").resolve(name);
+ ClassLoader loader = context.getClassLoader();
+ URL location = context.getScdlLocation();
+ // xcv test
+ DeploymentContext childContext = new ChildDeploymentContext(context, loader, location, componentId, autowire);
+ Implementation<?> impl = loadImplementation(reader, childContext);
+ registry.loadComponentType(impl, childContext);
+
+ ComponentDefinition<Implementation<?>> componentDefinition =
+ new ComponentDefinition<Implementation<?>>(componentId, impl);
+ componentDefinition.setAutowire(autowire);
+ if (initLevel != null) {
+ if (initLevel.length() == 0) {
+ componentDefinition.setInitLevel(0);
+ } else {
+ try {
+ componentDefinition.setInitLevel(Integer.valueOf(initLevel));
+ } catch (NumberFormatException e) {
+ throw new InvalidValueException(initLevel, "initValue", e);
+ }
+ }
+ }
+
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (PROPERTY.equals(qname)) {
+ loadProperty(reader, componentDefinition, childContext);
+ } else if (REFERENCE.equals(qname)) {
+ loadReference(reader, componentDefinition, childContext);
+ } else {
+ throw new UnrecognizedElementException(qname);
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(COMPONENT)) {
+ populatePropertyValues(componentDefinition);
+ ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> type =
+ (ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>) componentDefinition
+ .getImplementation().getComponentType();
+
+ for (ReferenceDefinition ref : type.getReferences().values()) {
+ // add reference target definitions if autowire is enabled for references that are not
+ // explicitly configured with autowire by the component
+ if (!componentDefinition.getReferenceTargets().containsKey(ref.getUri().getFragment())) {
+ if (autowire) {
+ ReferenceTarget referenceTarget = new ReferenceTarget();
+ String compName = componentDefinition.getUri().toString();
+ URI refName = URI.create(compName + ref.getUri().toString());
+ referenceTarget.setReferenceName(refName);
+ referenceTarget.setAutowire(autowire);
+ componentDefinition.add(referenceTarget);
+ }
+ }
+ }
+ validate(componentDefinition);
+ return componentDefinition;
+ }
+ break;
+ }
+ }
+ }
+
+ protected Implementation<?> loadImplementation(XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ reader.nextTag();
+ ModelObject o = registry.load(null, reader, context);
+ if (!(o instanceof Implementation)) {
+ throw new MissingImplementationException();
+ }
+ return (Implementation<?>) o;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void loadProperty(XMLStreamReader reader, ComponentDefinition<?> definition, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR);
+ Implementation<?> implementation = definition.getImplementation();
+ ComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ Property<Type> property = (Property<Type>) componentType.getProperties().get(name);
+ if (property == null) {
+ throw new UndefinedPropertyException(name);
+ }
+ PropertyValue<Type> propertyValue;
+ String source = reader.getAttributeValue(null, PROPERTY_SOURCE_ATTR);
+ String file = reader.getAttributeValue(null, PROPERTY_FILE_ATTR);
+ if (source != null || file != null) {
+ propertyValue = new PropertyValue<Type>(name, source, file);
+ propertyValue.setValue(property.getDefaultValue());
+ LoaderUtil.skipToEndElement(reader);
+ } else {
+ try {
+ DocumentBuilder documentBuilder = DOMHelper.newDocumentBuilder();
+ Document value = PropertyUtils.createPropertyValue(reader, property.getXmlType(), documentBuilder);
+ propertyValue = new PropertyValue<Type>(name, value);
+ } catch (ParserConfigurationException e) {
+ throw new LoaderException(e);
+ }
+ }
+ ObjectFactory<Type> objectFactory = propertyFactory.createObjectFactory(property, propertyValue);
+ propertyValue.setValueFactory(objectFactory);
+ definition.add(propertyValue);
+ }
+
+ protected void loadReference(XMLStreamReader reader,
+ ComponentDefinition<?> componentDefinition,
+ DeploymentContext context) throws XMLStreamException, LoaderException {
+ String name = reader.getAttributeValue(null, "name");
+ if (name == null) {
+ throw new InvalidReferenceException("No name specified");
+ }
+ String target = reader.getAttributeValue(null, "target");
+ boolean autowire = Boolean.parseBoolean(reader.getAttributeValue(null, "autowire"));
+ URI componentId = context.getComponentId();
+ List<URI> uris = new ArrayList<URI>();
+ if (target != null) {
+ StringTokenizer tokenizer = new StringTokenizer(target);
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ QualifiedName qName = new QualifiedName(token);
+ uris.add(componentId.resolve(qName.getFragment()));
+ }
+ }
+
+ Implementation<?> impl = componentDefinition.getImplementation();
+ ComponentType<?, ?, ?> componentType = impl.getComponentType();
+ if (!componentType.getReferences().containsKey(name)) {
+ throw new UndefinedReferenceException(name);
+ }
+ if (componentType instanceof CompositeComponentType) {
+ if (uris.size() != 1) {
+ // FIXME not yet implemented
+ throw new UnsupportedOperationException();
+ }
+ ReferenceDefinition definition = componentType.getReferences().get(name);
+ if (definition.getBindings().isEmpty()) {
+ // TODO JFM allow selection of a default binding
+ LocalBindingDefinition binding = new LocalBindingDefinition(uris.get(0));
+ definition.addBinding(binding);
+ } else {
+ for (BindingDefinition binding : definition.getBindings()) {
+ binding.setTargetUri(uris.get(0));
+ }
+ }
+ } else {
+ ReferenceTarget referenceTarget = componentDefinition.getReferenceTargets().get(name);
+ if (referenceTarget == null) {
+ referenceTarget = new ReferenceTarget();
+ referenceTarget.setReferenceName(componentId.resolve('#' + name));
+ referenceTarget.setAutowire(autowire);
+ componentDefinition.add(referenceTarget);
+ }
+ for (URI uri : uris) {
+ referenceTarget.addTarget(uri);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void populatePropertyValues(ComponentDefinition<Implementation<?>> componentDefinition)
+ throws MissingRequiredPropertyException {
+ ComponentType componentType = componentDefinition.getImplementation().getComponentType();
+ if (componentType != null) {
+ Map<String, Property<?>> properties = componentType.getProperties();
+ Map<String, PropertyValue<?>> propertyValues = componentDefinition.getPropertyValues();
+
+ for (Property<?> aProperty : properties.values()) {
+ if (propertyValues.get(aProperty.getName()) == null) {
+ if (aProperty.isRequired()) {
+ throw new MissingRequiredPropertyException(aProperty.getName());
+ } else if (aProperty.getDefaultValue() != null) {
+ PropertyValue propertyValue = new PropertyValue();
+ propertyValue.setName(aProperty.getName());
+ propertyValue.setValue(aProperty.getDefaultValue());
+ propertyValue.setValueFactory(new SimplePropertyObjectFactory(aProperty,
+ propertyValue.getValue()));
+ propertyValues.put(aProperty.getName(), propertyValue);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Validates a component definition, ensuring all component type configuration elements are satisfied
+ */
+ protected void validate(ComponentDefinition<Implementation<?>> definition) throws LoaderException {
+ // validate refererences
+ Implementation<?> implementation = definition.getImplementation();
+ ComponentType<?, ?, ?> type = implementation.getComponentType();
+ if (type == null) {
+ return;
+ }
+ for (ReferenceDefinition referenceDef : type.getReferences().values()) {
+ if (!referenceDef.isRequired()) {
+ continue;
+ }
+ String name = referenceDef.getUri().getFragment();
+ ReferenceTarget target = definition.getReferenceTargets().get(name);
+ if (target == null) {
+ throw new MissingReferenceException(name);
+ }
+ if (target.isAutowire()) {
+ // autowire targets are not set yet
+ continue;
+ }
+ int count = target.getTargets().size();
+ Multiplicity multiplicity = referenceDef.getMultiplicity();
+ switch (multiplicity) {
+ case ZERO_N:
+ break;
+ case ZERO_ONE:
+ if (count > 1) {
+ throw new ReferenceMultiplicityViolationException(name, multiplicity, count);
+ }
+ break;
+ case ONE_ONE:
+ if (count != 1) {
+ throw new ReferenceMultiplicityViolationException(name, multiplicity, count);
+ }
+ break;
+ case ONE_N:
+ if (count < 1) {
+ throw new ReferenceMultiplicityViolationException(name, multiplicity, count);
+ }
+ break;
+ }
+
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java
new file mode 100644
index 0000000000..beb0bc2731
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java
@@ -0,0 +1,86 @@
+/*
+ * 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.core.loader;
+
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ComponentTypeElementLoader extends LoaderExtension<ComponentType> {
+ public static final QName COMPONENT_TYPE = new QName(SCA_NS, "componentType");
+
+ @Constructor
+ public ComponentTypeElementLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return COMPONENT_TYPE;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ComponentType load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert COMPONENT_TYPE.equals(reader.getName());
+ ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> componentType;
+ if (object != null) {
+ assert object instanceof ComponentType;
+ // a specialized component type was passed in
+ componentType = (ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>) object;
+ } else {
+ componentType = new ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>();
+ }
+
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(componentType, reader, context);
+ if (o instanceof ServiceDefinition) {
+ componentType.add((ServiceDefinition) o);
+ } else if (o instanceof ReferenceDefinition) {
+ componentType.add((ReferenceDefinition) o);
+ } else if (o instanceof Property) {
+ componentType.add((Property<?>) o);
+ }
+ break;
+ case END_ELEMENT:
+ return componentType;
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java
new file mode 100644
index 0000000000..a4d1cd1440
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java
@@ -0,0 +1,88 @@
+/*
+ * 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.core.loader;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.services.artifact.Artifact;
+
+import org.apache.tuscany.core.implementation.composite.Dependency;
+
+/**
+ * Loader for handling <dependency> elements.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DependencyLoader extends LoaderExtension<Dependency> {
+ private static final String NS = "http://tuscany.apache.org/xmlns/sca/2.0-alpha";
+ private static final QName DEPENDENCY = new QName(NS, "dependency");
+ private static final QName GROUP = new QName(NS, "group");
+ private static final QName NAME = new QName(NS, "name");
+ private static final QName VERSION = new QName(NS, "version");
+ private static final QName CLASSIFIER = new QName(NS, "classifier");
+ private static final QName TYPE = new QName(NS, "type");
+
+ public DependencyLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return DEPENDENCY;
+ }
+
+ public Dependency load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ Artifact artifact = new Artifact();
+ while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) {
+ QName name = reader.getName();
+ String text = reader.getElementText();
+ if (GROUP.equals(name)) {
+ artifact.setGroup(text);
+ } else if (NAME.equals(name)) {
+ artifact.setName(text);
+ } else if (VERSION.equals(name)) {
+ artifact.setVersion(text);
+ } else if (CLASSIFIER.equals(name)) {
+ artifact.setClassifier(text);
+ } else if (TYPE.equals(name)) {
+ artifact.setType(text);
+ } else {
+ throw new UnrecognizedElementException(name);
+ }
+ }
+ Dependency dependency = new Dependency();
+ dependency.setArtifact(artifact);
+ return dependency;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java
new file mode 100644
index 0000000000..e10a93bbc0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java
@@ -0,0 +1,105 @@
+/*
+ * 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.core.loader;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.MissingIncludeException;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Include;
+import org.apache.tuscany.spi.model.ModelObject;
+
+import org.apache.tuscany.core.deployer.ChildDeploymentContext;
+
+/**
+ * Loader that handles &lt;include&gt; elements.
+ *
+ * @version $Rev$ $Date$
+ */
+public class IncludeLoader extends LoaderExtension<Include> {
+ private static final QName INCLUDE = new QName(SCA_NS, "include");
+
+ @Constructor
+ public IncludeLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return INCLUDE;
+ }
+
+ public Include load(ModelObject object, XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ assert INCLUDE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String scdlLocation = reader.getAttributeValue(null, "scdlLocation");
+ String scdlResource = reader.getAttributeValue(null, "scdlResource");
+ LoaderUtil.skipToEndElement(reader);
+
+ ClassLoader cl = deploymentContext.getClassLoader();
+ URL url;
+ if (scdlLocation != null) {
+ try {
+ url = new URL(deploymentContext.getScdlLocation(), scdlLocation);
+ } catch (MalformedURLException e) {
+ throw new MissingResourceException(scdlLocation, name, e);
+ }
+ } else if (scdlResource != null) {
+ url = cl.getResource(scdlResource);
+ if (url == null) {
+ throw new MissingResourceException(scdlResource, name);
+ }
+ } else {
+ throw new MissingIncludeException("No SCDL location or resource specified", name);
+ }
+
+ // when we include, the componentId remains that of the parent
+ URI componentId = deploymentContext.getComponentId();
+ boolean autowire = deploymentContext.isAutowire();
+ DeploymentContext childContext = new ChildDeploymentContext(deploymentContext, cl, url, componentId, autowire);
+ CompositeComponentType composite;
+ composite = loadFromSidefile(url, childContext);
+
+ Include include = new Include();
+ include.setName(name);
+ include.setScdlLocation(url);
+ include.setIncluded(composite);
+ return include;
+ }
+
+ protected CompositeComponentType loadFromSidefile(URL url, DeploymentContext context) throws LoaderException {
+ return registry.load(null, url, CompositeComponentType.class, context);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java
new file mode 100644
index 0000000000..8759377840
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.loader;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+
+import org.apache.tuscany.core.injection.JNDIObjectFactory;
+
+/**
+ * A StAXPropertyFactory that creates property values by looking them up in the default JNDI InitialContext. <p/> This
+ * can be used to locate resources in a J2EE environment and inject them as configuration properties. For example, to
+ * access a database a component could write: <code> &at;Property DataSource myDB; </code> and configure with <code>
+ * &lt;properties&gt; &lt;v:myDb&gt;java:comp/env/jdbc/MyDatabase&lt;/v:myDB&gt; &lt;/properties&gt; </code>
+ *
+ * @version $Rev$ $Date$
+ */
+public class JNDIPropertyFactory implements PropertyObjectFactory {
+ public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value)
+ throws LoaderException {
+ String text = value.getValue().getDocumentElement().getTextContent();
+ try {
+ Context context = new InitialContext();
+ return new JNDIObjectFactory<T>(context, text);
+ } catch (NamingException e) {
+ throw new LoaderException(e);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java
new file mode 100644
index 0000000000..26ec72ecb6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.core.loader;
+
+import java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.loader.LoaderException;
+
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+
+/**
+ * Formats {@link org.apache.tuscany.spi.loader.LoaderException} events
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class LoaderExceptionFormatter implements ExceptionFormatter {
+ private FormatterRegistry factory;
+
+ public LoaderExceptionFormatter(@Reference FormatterRegistry factory) {
+ this.factory = factory;
+ factory.register(this);
+ }
+
+ public boolean canFormat(Class<?> type) {
+ return LoaderException.class.isAssignableFrom(type);
+ }
+
+ @Destroy
+ public void destroy() {
+ factory.unregister(this);
+ }
+
+ public PrintWriter write(PrintWriter writer, Throwable exception) {
+ assert exception instanceof LoaderException;
+ LoaderException e = (LoaderException) exception;
+ e.appendBaseMessage(writer);
+ if (e.getLine() != LoaderException.UNDEFINED) {
+ writer.write("\nLine: " + e.getLine() + "\n");
+ writer.write("Column: " + e.getColumn() + "\n");
+ } else {
+ writer.write("\n");
+ }
+ return writer;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java
new file mode 100644
index 0000000000..57fd1da870
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java
@@ -0,0 +1,179 @@
+/*
+ * 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.core.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.loader.ComponentTypeLoader;
+import org.apache.tuscany.spi.loader.InvalidConfigurationException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.StAXElementLoader;
+import org.apache.tuscany.spi.loader.UnrecognizedComponentTypeException;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ModelObject;
+
+/**
+ * The default implementation of a loader registry
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class LoaderRegistryImpl implements LoaderRegistry {
+ private Monitor monitor;
+ private final Map<QName, StAXElementLoader<? extends ModelObject>> loaders =
+ new HashMap<QName, StAXElementLoader<? extends ModelObject>>();
+ private final Map<Class<? extends Implementation<?>>,
+ ComponentTypeLoader<? extends Implementation<?>>> componentTypeLoaders =
+ new HashMap<Class<? extends Implementation<?>>, ComponentTypeLoader<? extends Implementation<?>>>();
+
+ public LoaderRegistryImpl(@org.apache.tuscany.api.annotation.Monitor Monitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public <T extends ModelObject> void registerLoader(QName element, StAXElementLoader<T> loader) {
+ monitor.registeringLoader(element);
+ loaders.put(element, loader);
+ }
+
+ public <T extends ModelObject> void unregisterLoader(QName element, StAXElementLoader<T> loader) {
+ monitor.unregisteringLoader(element);
+ loaders.remove(element);
+ }
+
+ public ModelObject load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ QName name = reader.getName();
+ monitor.elementLoad(name);
+ StAXElementLoader<? extends ModelObject> loader = loaders.get(name);
+ if (loader == null) {
+ throw new UnrecognizedElementException(name);
+ }
+ return loader.load(object, reader, deploymentContext);
+ }
+
+ public <MO extends ModelObject> MO load(
+ ModelObject object,
+ URL url,
+ Class<MO> type,
+ DeploymentContext ctx) throws LoaderException {
+ try {
+ XMLStreamReader reader;
+ InputStream is;
+ is = url.openStream();
+ try {
+ XMLInputFactory factory = ctx.getXmlFactory();
+ reader = factory.createXMLStreamReader(is);
+ try {
+ reader.nextTag();
+ QName name = reader.getName();
+ ModelObject mo = load(object, reader, ctx);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(name);
+ e.setResourceURI(url.toString());
+ throw e;
+ }
+ } catch (LoaderException e) {
+ Location location = reader.getLocation();
+ e.setLine(location.getLineNumber());
+ e.setColumn(location.getColumnNumber());
+ throw e;
+ } finally {
+ try {
+ reader.close();
+ } catch (XMLStreamException e) {
+ // ignore
+ }
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ } catch (IOException e) {
+ LoaderException sfe = new LoaderException(e);
+ sfe.setResourceURI(url.toString());
+ throw sfe;
+ } catch (XMLStreamException e) {
+ throw new InvalidConfigurationException("Invalid or missing resource", url.toString(), e);
+ }
+ }
+
+ public <I extends Implementation<?>> void registerLoader(Class<I> key, ComponentTypeLoader<I> loader) {
+ componentTypeLoaders.put(key, loader);
+ }
+
+ public <I extends Implementation<?>> void unregisterLoader(Class<I> key) {
+ componentTypeLoaders.remove(key);
+ }
+
+ @SuppressWarnings("unchecked")
+ public <I extends Implementation<?>> void loadComponentType(I implementation,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ Class<I> key = (Class<I>) implementation.getClass();
+ ComponentTypeLoader<I> loader = (ComponentTypeLoader<I>) componentTypeLoaders.get(key);
+ if (loader == null) {
+ throw new UnrecognizedComponentTypeException(key);
+ }
+ loader.load(implementation, deploymentContext);
+ }
+
+ public static interface Monitor {
+ /**
+ * Event emitted when a StAX element loader is registered.
+ *
+ * @param xmlType the QName of the element the loader will handle
+ */
+ void registeringLoader(QName xmlType);
+
+ /**
+ * Event emitted when a StAX element loader is unregistered.
+ *
+ * @param xmlType the QName of the element the loader will handle
+ */
+ void unregisteringLoader(QName xmlType);
+
+ /**
+ * Event emitted when a request is made to load an element.
+ *
+ * @param xmlType the QName of the element that should be loaded
+ */
+ void elementLoad(QName xmlType);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java
new file mode 100644
index 0000000000..66d2a87593
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java
@@ -0,0 +1,195 @@
+/*
+ * 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.core.loader;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.model.IntentMap;
+import org.apache.tuscany.spi.model.IntentName;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.PolicySet;
+import org.apache.tuscany.spi.model.PolicySetReference;
+import org.apache.tuscany.spi.model.Qualifier;
+import org.apache.tuscany.spi.model.WSPolicyAttachment;
+
+/**
+ * Loads a PolicySet definition from an SCDL file.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PolicySetLoader extends LoaderExtension<PolicySet> {
+
+ private static final String WSPOLICY_NAMESPACE = "http://schemas.xmlsoap.org/ws/2004/09/policy";
+
+ private static final QName POLICYSET = new QName(SCA_NS, "policySet");
+
+ private static final QName INTENTMAP = new QName(SCA_NS, "intentMap");
+
+ private static final QName QUALIFIER = new QName(SCA_NS, "qualifier");
+
+ private static final QName POLICYSETREFERENCE = new QName(SCA_NS, "policySetReference");
+
+ private static final QName WSPOLICYATTACHMENT = new QName(WSPOLICY_NAMESPACE, "PolicyAttachment");
+
+ @Constructor
+ public PolicySetLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+
+ }
+
+ @Override
+ public QName getXMLType() {
+ return POLICYSET;
+ }
+
+ public PolicySet load(ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert POLICYSET.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String provides = reader.getAttributeValue(null, "provides");
+ String appliesTo = reader.getAttributeValue(null, "appliesTo");
+ PolicySet policySet = new PolicySet(new QName(SCA_NS, name), parseIntentName(provides));
+ String[] appliesToArtifact = split(appliesTo);
+ for (String artifact : appliesToArtifact) {
+ policySet.addAppliedArtifacts(new QName(SCA_NS, artifact));
+ }
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (INTENTMAP.equals(qname)) {
+ policySet.addIntentMap(loadIntentMap(reader, deploymentContext));
+ } else if (POLICYSETREFERENCE.equals(qname)) {
+ policySet.addPolicySetReference(loadPolicyReference(reader, deploymentContext));
+ } else if (WSPOLICYATTACHMENT.equals(qname)) {
+ policySet.addWsPolicyAttachment(loadWSPolicyAttachment(reader, deploymentContext));
+ }
+
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(POLICYSET)) {
+ return policySet;
+ }
+ break;
+ }
+ }
+
+ }
+
+ private PolicySetReference loadPolicyReference(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert POLICYSETREFERENCE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ LoaderUtil.skipToEndElement(reader);
+ return new PolicySetReference(new QName(SCA_NS, name));
+ }
+
+ private IntentMap loadIntentMap(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert INTENTMAP.equals(reader.getName());
+ String defaultIntentAttr = reader.getAttributeValue(null, "default");
+ String provides = reader.getAttributeValue(null, "provides");
+ IntentMap intentMap = new IntentMap(defaultIntentAttr, java.util.Arrays.asList(split(provides)));
+ //parentPolicySet.addIntentMap(intentMap);
+
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (QUALIFIER.equals(qname)) {
+ intentMap.addQualifier(loadQualifier(reader, deploymentContext));
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(INTENTMAP)) {
+ return intentMap;
+ }
+ }
+ }
+
+ }
+
+ private Qualifier loadQualifier(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ assert QUALIFIER.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ Qualifier qualifier = new Qualifier(name);
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (INTENTMAP.equals(qname)) {
+ qualifier.setIntentMap(loadIntentMap(reader, deploymentContext));
+ } else if (WSPOLICYATTACHMENT.equals(qname)) {
+ qualifier.addWsPolicyAttachment(loadWSPolicyAttachment(reader, deploymentContext));
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(QUALIFIER)) {
+ return qualifier;
+ }
+ }
+ }
+
+ }
+
+ private WSPolicyAttachment loadWSPolicyAttachment(XMLStreamReader reader, DeploymentContext deploymentContext)
+ throws XMLStreamException {
+ return new WSPolicyAttachment();
+ }
+
+ /**
+ * Split a string to string array separated by " "
+ */
+ private static String[] split(String string) {
+ if (string == null) {
+ return new String[0];
+ }
+ String[] intents = string.split("[ ]+");
+ return intents;
+ }
+
+ private static List<IntentName> parseIntentName(String attributes) {
+ String[] intents = split(attributes);
+ List<IntentName> result = new ArrayList<IntentName>(intents.length);
+ for (String intent : intents) {
+ result.add(new IntentName(intent));
+ }
+ return result;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java
new file mode 100644
index 0000000000..ac39c135d9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java
@@ -0,0 +1,98 @@
+/*
+ * 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.core.loader;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.w3c.dom.Document;
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Property;
+
+/**
+ * Loads a property from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class PropertyLoader extends LoaderExtension<Property> {
+ public static final String PROPERTY_NAME_ATTR = "name";
+ public static final String PROPERTY_TYPE_ATTR = "type";
+ public static final String PROPERTY_MANY_ATTR = "many";
+ public static final String REQUIRED_ATTR = "override";
+
+ public static final QName PROPERTY = new QName(SCA_NS, "property");
+ private final DocumentBuilder documentBuilder;
+
+ @Constructor
+ public PropertyLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ try {
+ documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ // we should be able to construct the default DocumentBuilder
+ throw new AssertionError(e);
+ }
+ }
+
+ public QName getXMLType() {
+ return PROPERTY;
+ }
+
+ public Property<?> load(ModelObject object, XMLStreamReader reader,
+ DeploymentContext ctx)
+ throws XMLStreamException, LoaderException {
+ assert PROPERTY.equals(reader.getName());
+ String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR);
+ String typeName = reader.getAttributeValue(null, PROPERTY_TYPE_ATTR);
+ QName xmlType = null;
+ if (typeName != null) {
+ int index = typeName.indexOf(':');
+ if (index != -1) {
+ String prefix = typeName.substring(0, index);
+ String localName = typeName.substring(index + 1);
+ String ns = reader.getNamespaceURI(prefix);
+ xmlType = new QName(ns, localName, prefix);
+ }
+ }
+ boolean many = Boolean.parseBoolean(reader.getAttributeValue(null, PROPERTY_MANY_ATTR));
+ String required = reader.getAttributeValue(null, REQUIRED_ATTR);
+ Document value = PropertyUtils.createPropertyValue(reader, xmlType, documentBuilder);
+
+ Property<?> property = new Property();
+ property.setRequired(Boolean.parseBoolean(required));
+ property.setName(name);
+ property.setXmlType(xmlType);
+ property.setMany(many);
+
+ property.setDefaultValue(value);
+ return property;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java
new file mode 100644
index 0000000000..57c1e1b5f4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/PropertyUtils.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.loader;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public final class PropertyUtils {
+
+ private PropertyUtils() {
+ }
+
+ public static Document createPropertyValue(XMLStreamReader reader, QName type, DocumentBuilder builder)
+ throws XMLStreamException {
+ Document doc = builder.newDocument();
+
+ // root element has no namespace and local name "value"
+ Element root = doc.createElementNS(null, "value");
+ if (type != null) {
+ Attr xsi = doc.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi");
+ xsi.setValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI);
+ root.setAttributeNodeNS(xsi);
+
+ String prefix = type.getPrefix();
+ if (prefix == null || prefix.length() == 0) {
+ prefix = "ns";
+ }
+ Attr typeXmlns = doc.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:" + prefix);
+ typeXmlns.setValue(type.getNamespaceURI());
+ root.setAttributeNodeNS(typeXmlns);
+
+ Attr xsiType = doc.createAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type");
+ xsiType.setValue(prefix + ":" + type.getLocalPart());
+ root.setAttributeNodeNS(xsiType);
+ }
+ doc.appendChild(root);
+
+ loadPropertyValue(reader, root);
+ return doc;
+ }
+
+ /**
+ * Load a property value specification from an StAX stream into a DOM Document. Only elements, text and attributes
+ * are processed; all comments and other whitespace are ignored.
+ *
+ * @param reader the stream to read from
+ * @param root the DOM node to load
+ * @throws javax.xml.stream.XMLStreamException
+ *
+ */
+ public static void loadPropertyValue(XMLStreamReader reader, Node root) throws XMLStreamException {
+ Document document = root.getOwnerDocument();
+ Node current = root;
+ while (true) {
+ switch (reader.next()) {
+ case XMLStreamConstants.START_ELEMENT:
+ QName name = reader.getName();
+ Element child = document.createElementNS(name.getNamespaceURI(), name.getLocalPart());
+
+ // add the attributes for this element
+ int count = reader.getAttributeCount();
+ for (int i = 0; i < count; i++) {
+ String ns = reader.getAttributeNamespace(i);
+ String localPart = reader.getAttributeLocalName(i);
+ String value = reader.getAttributeValue(i);
+ child.setAttributeNS(ns, localPart, value);
+ }
+
+ // push the new element and make it the current one
+ current.appendChild(child);
+ current = child;
+ break;
+ case XMLStreamConstants.CDATA:
+ current.appendChild(document.createCDATASection(reader.getText()));
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ current.appendChild(document.createTextNode(reader.getText()));
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ // if we are back at the root then we are done
+ if (current == root) {
+ return;
+ }
+
+ // pop the element off the stack
+ current = current.getParentNode();
+ }
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java
new file mode 100644
index 0000000000..54183d1c72
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java
@@ -0,0 +1,107 @@
+/*
+ * 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.core.loader;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+/**
+ * Loads a reference from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReferenceLoader extends LoaderExtension<ReferenceDefinition> {
+ public static final QName REFERENCE = new QName(SCA_NS, "reference");
+ private static final Map<String, Multiplicity> MULTIPLICITY = new HashMap<String, Multiplicity>(4);
+
+ static {
+ MULTIPLICITY.put("0..1", Multiplicity.ZERO_ONE);
+ MULTIPLICITY.put("1..1", Multiplicity.ONE_ONE);
+ MULTIPLICITY.put("0..n", Multiplicity.ZERO_N);
+ MULTIPLICITY.put("1..n", Multiplicity.ONE_N);
+ }
+
+ @Constructor
+ public ReferenceLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return REFERENCE;
+ }
+
+ public ReferenceDefinition load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert REFERENCE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String multiplicityVal = reader.getAttributeValue(null, "multiplicity");
+ Multiplicity multiplicity = multiplicity(multiplicityVal, Multiplicity.ONE_ONE);
+ ReferenceDefinition referenceDefinition = new ReferenceDefinition();
+ referenceDefinition.setMultiplicity(multiplicity);
+ referenceDefinition.setUri(context.getComponentId().resolve('#' + name));
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(null, reader, context);
+ if (o instanceof ServiceContract) {
+ referenceDefinition.setServiceContract((ServiceContract) o);
+ } else if (o instanceof BindingDefinition) {
+ referenceDefinition.addBinding((BindingDefinition) o);
+ } else {
+ throw new UnrecognizedElementException(reader.getName());
+ }
+ break;
+ case END_ELEMENT:
+ return referenceDefinition;
+ }
+ }
+ }
+
+ /**
+ * Convert a "multiplicity" attribute to the equivalent enum value.
+ *
+ * @param multiplicity the attribute to convert
+ * @param def the default value
+ * @return the enum equivalent
+ */
+ private static Multiplicity multiplicity(String multiplicity, Multiplicity def) {
+ return multiplicity == null ? def : MULTIPLICITY.get(multiplicity);
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java
new file mode 100644
index 0000000000..c5be797cda
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.loader;
+
+import java.net.URI;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.UnrecognizedElementException;
+import org.apache.tuscany.spi.model.BindingDefinition;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+/**
+ * Loads a service definition from an XML-based assembly file
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServiceLoader extends LoaderExtension<ServiceDefinition> {
+ private static final QName SERVICE = new QName(SCA_NS, "service");
+
+ @Constructor
+ public ServiceLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return SERVICE;
+ }
+
+ public ServiceDefinition load(ModelObject object, XMLStreamReader reader, DeploymentContext context)
+ throws XMLStreamException, LoaderException {
+ assert SERVICE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ URI compositeId = context.getComponentId();
+ URI componentBase = URI.create(compositeId + "/");
+ ServiceDefinition def = new ServiceDefinition();
+ def.setUri(compositeId.resolve('#' + name));
+
+ URI targetUri = null;
+ String promote = reader.getAttributeValue(null, "promote");
+ if (promote != null) {
+ QualifiedName qName = new QualifiedName(promote);
+ targetUri = componentBase.resolve(qName.getFragment());
+ }
+ while (true) {
+ int i = reader.next();
+ switch (i) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(null, reader, context);
+ if (o instanceof ServiceContract) {
+ def.setServiceContract((ServiceContract) o);
+ } else if (o instanceof BindingDefinition) {
+ def.addBinding((BindingDefinition) o);
+ } else {
+ throw new UnrecognizedElementException(reader.getName());
+ }
+ break;
+ case END_ELEMENT:
+ if (SERVICE.equals(reader.getName())) {
+ if (targetUri != null) {
+ def.setTarget(targetUri);
+ }
+ return def;
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java
new file mode 100644
index 0000000000..eda09d6f11
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java
@@ -0,0 +1,191 @@
+/*
+ * 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.core.loader;
+
+import java.beans.PropertyEditor;
+import java.beans.PropertyEditorManager;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+
+import org.apache.tuscany.core.injection.SingletonObjectFactory;
+
+/**
+ * Implementation of StAXPropertyFactory that interprets the XML as
+ *
+ * @version $Rev$ $Date$
+ */
+public class StringParserPropertyFactory implements PropertyObjectFactory {
+
+ public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value)
+ throws LoaderException {
+ String text = value.getValue().getDocumentElement().getTextContent();
+ return new SingletonObjectFactory<T>(createInstance(text, property.getJavaType()));
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T createInstance(String text, Class<T> type) throws LoaderException {
+ // Class<T> type = property.getJavaType();
+ assert type != null : "property type is null";
+
+ // degenerate case where property type is a String
+ if (String.class.equals(type)) {
+ return type.cast(text);
+ }
+
+ // special handler to convert hexBinary to a byte[]
+ if (byte[].class.equals(type)) {
+ byte[] instance = new byte[text.length() >> 1];
+ for (int i = 0; i < instance.length; i++) {
+ instance[i] =
+ (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text
+ .charAt((i << 1) + 1), 16));
+ }
+ return type.cast(instance);
+ }
+
+ // does this type have a static valueOf(String) method?
+ try {
+ Method valueOf = type.getMethod("valueOf", String.class);
+ if (Modifier.isStatic(valueOf.getModifiers())) {
+ try {
+ return type.cast(valueOf.invoke(null, text));
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getMethod returned an inaccessible method");
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ // try something else
+ }
+
+ // does this type have a constructor that takes a String?
+ try {
+ Constructor<T> ctr = type.getConstructor(String.class);
+ return ctr.newInstance(text);
+ } catch (NoSuchMethodException e) {
+ // try something else
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getConstructor returned an inaccessible method");
+ } catch (InstantiationException e) {
+ throw new LoaderException("Property type cannot be instantiated: " + type.getName());
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+
+ // do we have a property editor for it?
+ PropertyEditor editor = PropertyEditorManager.findEditor(type);
+ if (editor != null) {
+ try {
+ editor.setAsText(text);
+ return (T) editor.getValue();
+ } catch (IllegalArgumentException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e);
+
+ }
+ }
+
+ // FIXME we should throw something better
+ throw new LoaderException("Do not have a way to parse a String into a " + type.getName());
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> ObjectFactory<T> createObjectFactory(String text, Property<T> property)
+ throws XMLStreamException, LoaderException {
+ Class<T> type = property.getJavaType();
+ assert type != null : "property type is null";
+
+ // degenerate case where property type is a String
+ if (String.class.equals(type)) {
+ return new SingletonObjectFactory<T>(type.cast(text));
+ }
+
+ // special handler to convert hexBinary to a byte[]
+ if (byte[].class.equals(type)) {
+ byte[] instance = new byte[text.length() >> 1];
+ for (int i = 0; i < instance.length; i++) {
+ instance[i] =
+ (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text
+ .charAt((i << 1) + 1), 16));
+ }
+ return new SingletonObjectFactory<T>(type.cast(instance));
+ }
+
+ // does this type have a static valueOf(String) method?
+ try {
+ Method valueOf = type.getMethod("valueOf", String.class);
+ if (Modifier.isStatic(valueOf.getModifiers())) {
+ try {
+ return new SingletonObjectFactory<T>(type.cast(valueOf.invoke(null, text)));
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getMethod returned an inaccessible method");
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ // try something else
+ }
+
+ // does this type have a constructor that takes a String?
+ try {
+ Constructor<T> ctr = type.getConstructor(String.class);
+ return new SingletonObjectFactory<T>(ctr.newInstance(text));
+ } catch (NoSuchMethodException e) {
+ // try something else
+ } catch (IllegalAccessException e) {
+ throw new AssertionError("getConstructor returned an inaccessible method");
+ } catch (InstantiationException e) {
+ throw new LoaderException("Property type cannot be instantiated: " + type.getName());
+ } catch (InvocationTargetException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e.getCause());
+ }
+
+ // do we have a property editor for it?
+ PropertyEditor editor = PropertyEditorManager.findEditor(type);
+ if (editor != null) {
+ try {
+ editor.setAsText(text);
+ return new SingletonObjectFactory<T>((T) editor.getValue());
+ } catch (IllegalArgumentException e) {
+ // FIXME we should throw something better
+ throw new LoaderException(e);
+
+ }
+ }
+
+ // FIXME we should throw something better
+ throw new LoaderException("Do not have a way to parse a String into a " + type.getName());
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java
new file mode 100644
index 0000000000..9c60790111
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java
@@ -0,0 +1,122 @@
+/*
+ * 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.core.loader;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import javax.xml.namespace.QName;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Constants.SCA_NS;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.InvalidWireException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.WireDefinition;
+
+/**
+ * Loads a wire from an XML-based assembly file
+ *
+ * @version $Rev: 465084 $ $Date: 2006-10-18 04:00:49 +0530 (Wed, 18 Oct 2006) $
+ */
+public class WireLoader extends LoaderExtension<WireDefinition> {
+ private static final QName WIRE = new QName(SCA_NS, "wire");
+ private static final QName SOURCE_URI = new QName(SCA_NS, "source.uri");
+ private static final QName TARGET_URI = new QName(SCA_NS, "target.uri");
+
+ @Constructor
+ public WireLoader(@Reference LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return WIRE;
+ }
+
+ public WireDefinition load(
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ assert WIRE.equals(reader.getName());
+ WireDefinition wireDefn;
+ URI sourceURI = null;
+ URI targetURI = null;
+ String uriString;
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ try {
+ if (reader.getName().equals(SOURCE_URI)) {
+ uriString = reader.getElementText();
+ if (uriString != null && uriString.trim().length() > 0) {
+ QualifiedName name = new QualifiedName(uriString);
+ if (name.getPortName() == null) {
+ sourceURI = new URI(uriString);
+ } else {
+ sourceURI = new URI(name.getPartName() + "#" + name.getPortName());
+ }
+ } else {
+ throw new InvalidWireException("Wire source not defined");
+ }
+ } else if (reader.getName().equals(TARGET_URI)) {
+ uriString = reader.getElementText();
+ if (uriString != null && uriString.trim().length() > 0) {
+ QualifiedName name = new QualifiedName(uriString);
+ if (name.getPortName() == null) {
+ targetURI = new URI(uriString);
+ } else {
+ targetURI = new URI(name.getPartName() + "#" + name.getPortName());
+ }
+ } else {
+ throw new InvalidWireException("Wire target not defined");
+ }
+ } else {
+ QName name = reader.getName();
+ throw new InvalidWireException("Unrecognized element in wire ", name.toString());
+ }
+ } catch (URISyntaxException e) {
+ throw new InvalidWireException("Invalid wire uri", e);
+ }
+
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(WIRE)) {
+ if (sourceURI != null && targetURI != null) {
+ wireDefn = new WireDefinition();
+ wireDefn.setSource(sourceURI);
+ wireDefn.setTarget(targetURI);
+ } else {
+ throw new InvalidWireException("Incomplete wire definition");
+ }
+ return wireDefn;
+ }
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/AbstractMarshallerExtension.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/AbstractMarshallerExtension.java
new file mode 100644
index 0000000000..16bf6ea178
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/AbstractMarshallerExtension.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.marshaller;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.marshaller.ModelMarshaller;
+import org.apache.tuscany.spi.marshaller.ModelMarshallerRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * Abstract marshaller that supports marshaller registry.
+ *
+ * @version $Revision$ $Date: 2007-03-03 12:17:30 +0000 (Sat, 03 Mar
+ * 2007) $
+ * @param <MD>
+ */
+public abstract class AbstractMarshallerExtension<MD extends ModelObject> implements ModelMarshaller<MD> {
+
+ // Private Model marshaller registry
+ protected ModelMarshallerRegistry registry;
+
+ /**
+ * Injects the model marshaller registry.
+ *
+ * @param registry Model marshaller registry.
+ */
+ @Reference
+ public final void setRegistry(ModelMarshallerRegistry registry) {
+
+ this.registry = registry;
+
+ Class<MD> marshallerType = getModelObjectType();
+ QName marshallerQName = getModelObjectQName();
+
+ registry.registerMarshaller(marshallerType, marshallerQName, this);
+
+ }
+
+ /**
+ * Gets the qualified name of the XML fragment for the marshalled model
+ * object.
+ *
+ * @return Qualified name of the XML fragment.
+ */
+ protected abstract QName getModelObjectQName();
+
+ /**
+ * Retursn the type of the model object.
+ *
+ * @return Model object type.
+ */
+ protected abstract Class<MD> getModelObjectType();
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/DefaultModelMarshallerRegistry.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/DefaultModelMarshallerRegistry.java
new file mode 100644
index 0000000000..6b502eac59
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/DefaultModelMarshallerRegistry.java
@@ -0,0 +1,97 @@
+/*
+ * 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.core.marshaller;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.marshaller.ModelMarshaller;
+import org.apache.tuscany.spi.marshaller.ModelMarshallerRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+
+/**
+ * Default map-based implementation of the model marshaller registry.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultModelMarshallerRegistry implements ModelMarshallerRegistry {
+
+ // Marshaller registry
+ private final Map<Class<? extends ModelObject>, ModelMarshaller> marshallerRegistry =
+ new ConcurrentHashMap<Class<? extends ModelObject>, ModelMarshaller>();
+
+ // Unmarshaller registry
+ private final Map<QName, ModelMarshaller> unmarshallerRegistry = new ConcurrentHashMap<QName, ModelMarshaller>();
+
+ /**
+ * Registers a model object marshaller.
+ *
+ * @param <MD> Model object type.
+ * @param modelClass Model obejct class.
+ * @param qname Qualified name of the root element of the marshalled XML.
+ * @param marshaller Model object marshaller.
+ */
+ public <MD extends ModelObject> void registerMarshaller(Class<MD> modelClass,
+ QName qname,
+ ModelMarshaller<MD> marshaller) {
+ marshallerRegistry.put(modelClass, marshaller);
+ unmarshallerRegistry.put(qname, marshaller);
+ }
+
+ /**
+ * Marshalls a model object.
+ *
+ * @param modelObject Model object to be marshalled.
+ * @param writer Writer to which marshalled information is written.
+ */
+ @SuppressWarnings("unchecked")
+ public void marshall(ModelObject modelObject, XMLStreamWriter writer) throws MarshallException {
+
+ ModelMarshaller marshaller = marshallerRegistry.get(modelObject.getClass());
+ if (marshaller == null) {
+ throw new MarshallException("No marshaller defined for " + modelObject.getClass());
+ }
+ marshaller.marshall(modelObject, writer);
+
+ }
+
+ /**
+ * Unmarshalls an XML stream to a model object.
+ *
+ * @param reader Reader from which marshalled information is read.
+ * @return Model object from the marshalled stream.
+ */
+ public ModelObject unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ QName qname = reader.getName();
+
+ ModelMarshaller marshaller = unmarshallerRegistry.get(qname);
+ if (marshaller == null) {
+ throw new MarshallException("No marshaller defined for " + qname);
+ }
+ return marshaller.unmarshall(reader);
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalChangeSetMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalChangeSetMarshaller.java
new file mode 100644
index 0000000000..e10a06b004
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalChangeSetMarshaller.java
@@ -0,0 +1,97 @@
+/*
+ * 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.core.marshaller;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.physical.PhysicalChangeSet;
+import org.apache.tuscany.spi.model.physical.PhysicalComponentDefinition;
+import org.apache.tuscany.spi.model.physical.PhysicalWireDefinition;
+
+/**
+ * Marshaller for physical changeset.
+ *
+ * @version $Revision$ $Date$
+ *
+ */
+public class PhysicalChangeSetMarshaller extends AbstractMarshallerExtension<PhysicalChangeSet> {
+
+ // QName for the root element
+ public static final QName QNAME = new QName("http://tuscany.apache.org/xmlns/marshaller/1.0-SNAPSHOT", "changeSet");
+
+ // Local part for wire
+ private static final String WIRE = "wire";
+
+ // Local part for component
+ private static final String COMPONENT = "component";
+
+ /**
+ * Marshalls a physical change set to the xml writer.
+ */
+ public void marshall(PhysicalChangeSet modelObject, XMLStreamWriter writer) throws MarshallException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unmarshalls a physical change set from the xml reader.
+ */
+ public PhysicalChangeSet unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ try {
+ PhysicalChangeSet changeSet = new PhysicalChangeSet();
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ String name = reader.getName().getLocalPart();
+ ModelObject modelObject = registry.unmarshall(reader);
+ if (COMPONENT.equals(name)) {
+ changeSet.addComponentDefinition((PhysicalComponentDefinition)modelObject);
+ } else if (WIRE.equals(name)) {
+ changeSet.addWireDefinition((PhysicalWireDefinition)modelObject);
+ }
+ break;
+ case END_DOCUMENT:
+ return changeSet;
+ }
+ }
+ } catch (XMLStreamException ex) {
+ throw new MarshallException(ex);
+ }
+
+ }
+
+ @Override
+ protected QName getModelObjectQName() {
+ return QNAME;
+ }
+
+ @Override
+ protected Class<PhysicalChangeSet> getModelObjectType() {
+ return PhysicalChangeSet.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalOperationDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalOperationDefinitionMarshaller.java
new file mode 100644
index 0000000000..4fe35e11ee
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalOperationDefinitionMarshaller.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.marshaller;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.physical.PhysicalOperationDefinition;
+
+/**
+ * Marshaller for physical operation definition.
+ *
+ * @version $Revision$ $Date: 2007-03-03 11:36:03 +0000 (Sat, 03 Mar
+ * 2007) $
+ */
+public class PhysicalOperationDefinitionMarshaller extends AbstractMarshallerExtension<PhysicalOperationDefinition> {
+
+ // Source name attribute
+ private static final String NAME = "name";
+
+ // QName for the root element
+ private static final QName QNAME =
+ new QName("http://tuscany.apache.org/xmlns/marshaller/1.0-SNAPSHOT", "operation");
+
+ /**
+ * Marshalls a physical operation to the xml writer.
+ */
+ public void marshall(PhysicalOperationDefinition modelObject, XMLStreamWriter writer) throws MarshallException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unmarshalls a physical operation from the xml reader.
+ */
+ public PhysicalOperationDefinition unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ PhysicalOperationDefinition operation = new PhysicalOperationDefinition();
+ operation.setName(reader.getAttributeValue(null, NAME));
+ operation.setCallback(Boolean.valueOf(reader.getAttributeValue(null, NAME)));
+ return operation;
+
+ }
+
+ @Override
+ protected QName getModelObjectQName() {
+ return QNAME;
+ }
+
+ @Override
+ protected Class<PhysicalOperationDefinition> getModelObjectType() {
+ return PhysicalOperationDefinition.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalWireDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalWireDefinitionMarshaller.java
new file mode 100644
index 0000000000..c8dfd37fac
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/PhysicalWireDefinitionMarshaller.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.marshaller;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.physical.PhysicalOperationDefinition;
+import org.apache.tuscany.spi.model.physical.PhysicalWireDefinition;
+
+/**
+ * Marshaller for physical wire definition.
+ *
+ * @version $Revision$ $Date: 2007-03-03 11:36:03 +0000 (Sat, 03 Mar
+ * 2007) $
+ */
+public class PhysicalWireDefinitionMarshaller extends AbstractMarshallerExtension<PhysicalWireDefinition> {
+
+ // Source URI attribute
+ private static final String SOURCE_URI = "sourceUri";
+
+ // Source URI attribute
+ private static final String TARGET_URI = "targetUri";
+
+ // QName for the root element
+ private static final QName QNAME = new QName("http://tuscany.apache.org/xmlns/marshaller/1.0-SNAPSHOT", "wire");
+
+ /**
+ * Marshalls a physical wire to the xml writer.
+ */
+ public void marshall(PhysicalWireDefinition modelObject, XMLStreamWriter writer) throws MarshallException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unmarshalls a physical wire from the xml reader.
+ */
+ public PhysicalWireDefinition unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ try {
+ PhysicalWireDefinition wireDefinition = new PhysicalWireDefinition();
+ wireDefinition.setSourceUri(new URI(reader.getAttributeValue(null, SOURCE_URI)));
+ wireDefinition.setTargetUri(new URI(reader.getAttributeValue(null, TARGET_URI)));
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject modelObject = registry.unmarshall(reader);
+ wireDefinition.addOperation((PhysicalOperationDefinition)modelObject);
+ break;
+ case END_ELEMENT:
+ return wireDefinition;
+
+ }
+ }
+ } catch (XMLStreamException ex) {
+ throw new MarshallException(ex);
+ } catch (URISyntaxException ex) {
+ throw new MarshallException(ex);
+ }
+
+ }
+
+ @Override
+ protected QName getModelObjectQName() {
+ return QNAME;
+ }
+
+ @Override
+ protected Class<PhysicalWireDefinition> getModelObjectType() {
+ return PhysicalWireDefinition.class;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractExtensibleMarshallerExtension.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractExtensibleMarshallerExtension.java
new file mode 100644
index 0000000000..090797e349
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractExtensibleMarshallerExtension.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.marshaller.extensions;
+
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.core.marshaller.AbstractMarshallerExtension;
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.ModelObject;
+
+/**
+ * Abstract marshaller that supports extensible model objects.
+ *
+ * @version $Revision$ $Date: 2007-03-04 18:23:24 +0000 (Sun, 04 Mar
+ * 2007) $
+ * @param <MD>
+ */
+public abstract class AbstractExtensibleMarshallerExtension<MD extends ModelObject> extends
+ AbstractMarshallerExtension<MD> {
+
+ /**
+ * Create the concrete model object.
+ *
+ * @return Concrete model object.
+ */
+ protected abstract MD getConcreteModelObject();
+
+ /**
+ * Handles extensions for unmarshalling.
+ *
+ * @param modelObject Concrete model object.
+ * @param reader Reader from which marshalled data is read.
+ */
+ protected abstract void handleExtension(MD modelObject, XMLStreamReader reader) throws MarshallException;
+
+ /**
+ * Handles extensions for marshalling.
+ *
+ * @param modelObject Concrete model object.
+ * @param reader Writer to which marshalled data is written.
+ */
+ protected abstract void handleExtension(MD modelObject, XMLStreamWriter writer) throws MarshallException;
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalComponentDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalComponentDefinitionMarshaller.java
new file mode 100644
index 0000000000..bcf868ad1e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalComponentDefinitionMarshaller.java
@@ -0,0 +1,110 @@
+/*
+ * 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.core.marshaller.extensions;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.physical.PhysicalComponentDefinition;
+
+/**
+ * Abstract super class for all PCD marshallers.
+ *
+ * @version $Revision$ $Date: 2007-03-03 16:41:22 +0000 (Sat, 03 Mar
+ * 2007) $
+ */
+public abstract class AbstractPhysicalComponentDefinitionMarshaller<PCD extends PhysicalComponentDefinition<?, ?>>
+ extends AbstractExtensibleMarshallerExtension<PCD> {
+
+ // Component id attribute
+ private static final String COMPONENT_ID = "componentId";
+
+ // Reference
+ private static final String REFERENCE = "reference";
+
+ // Service
+ private static final String SERVICE = "service";
+
+ /**
+ * Marshalls a physical change set to the xml writer.
+ */
+ public final void marshall(PCD modelObject, XMLStreamWriter writer) throws MarshallException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unmarshalls a physical change set from the xml reader.
+ */
+ public final PCD unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ try {
+ PCD componentDefinition = getConcreteModelObject();
+ componentDefinition.setComponentId(new URI(reader.getAttributeValue(null, COMPONENT_ID)));
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ String name = reader.getName().getLocalPart();
+ if (REFERENCE.equals(name)) {
+ handleReference(componentDefinition, reader);
+ } else if (SERVICE.equals(name)) {
+ handleService(componentDefinition, reader);
+ } else {
+ handleExtension(componentDefinition, reader);
+ }
+ break;
+ case END_ELEMENT:
+ if (getModelObjectQName().equals(reader.getName())) {
+ return componentDefinition;
+ }
+
+ }
+ }
+ } catch (XMLStreamException ex) {
+ throw new MarshallException(ex);
+ } catch (URISyntaxException ex) {
+ throw new MarshallException(ex);
+ }
+
+ }
+
+ /**
+ * Handles a reference.
+ *
+ * @param componentDefinition Component definition.
+ * @param reader XML stream.
+ */
+ protected abstract void handleReference(PCD componentDefinition, XMLStreamReader reader) throws MarshallException;
+
+ /**
+ * Handles a reference.
+ *
+ * @param componentDefinition Component definition.
+ * @param reader XML stream.
+ */
+ protected abstract void handleService(PCD componentDefinition, XMLStreamReader reader) throws MarshallException;
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalReferenceDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalReferenceDefinitionMarshaller.java
new file mode 100644
index 0000000000..f8b7d9e9e7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalReferenceDefinitionMarshaller.java
@@ -0,0 +1,84 @@
+/*
+ * 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.core.marshaller.extensions;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.physical.PhysicalOperationDefinition;
+import org.apache.tuscany.spi.model.physical.PhysicalReferenceDefinition;
+
+/**
+ * Marshaller for java physical reference definition.
+ *
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractPhysicalReferenceDefinitionMarshaller<PRD extends PhysicalReferenceDefinition> extends
+ AbstractExtensibleMarshallerExtension<PRD> {
+
+ // Local part for operation
+ private static final String OPERATION = "operation";
+
+ // Source name attribute
+ private static final String NAME = "name";
+
+ /**
+ * Marshalls a physical java reference definition to the xml writer.
+ */
+ public void marshall(PRD modelObject, XMLStreamWriter writer) throws MarshallException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unmarshalls a java physical reference definition from the xml reader.
+ */
+ public PRD unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ try {
+ PRD referenceDefinition = getConcreteModelObject();
+ referenceDefinition.setName(reader.getAttributeValue(null, NAME));
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject modelObject = registry.unmarshall(reader);
+ String name = reader.getName().getLocalPart();
+ if (OPERATION.equals(name)) {
+ referenceDefinition.addOperation((PhysicalOperationDefinition)modelObject);
+ } else {
+ handleExtension(referenceDefinition, reader);
+ }
+ break;
+ case END_ELEMENT:
+ return referenceDefinition;
+
+ }
+ }
+ } catch (XMLStreamException ex) {
+ throw new MarshallException(ex);
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalServiceDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalServiceDefinitionMarshaller.java
new file mode 100644
index 0000000000..7adb3f7ae2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/AbstractPhysicalServiceDefinitionMarshaller.java
@@ -0,0 +1,84 @@
+/*
+ * 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.core.marshaller.extensions;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.model.physical.PhysicalOperationDefinition;
+import org.apache.tuscany.spi.model.physical.PhysicalServiceDefinition;
+
+/**
+ * Marshaller for java physical service definition.
+ *
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractPhysicalServiceDefinitionMarshaller<PSD extends PhysicalServiceDefinition> extends
+ AbstractExtensibleMarshallerExtension<PSD> {
+
+ // Local part for operation
+ private static final String OPERATION = "operation";
+
+ // Source name attribute
+ private static final String NAME = "name";
+
+ /**
+ * Marshalls a physical java reference definition to the xml writer.
+ */
+ public void marshall(PSD modelObject, XMLStreamWriter writer) throws MarshallException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unmarshalls a java physical reference definition from the xml reader.
+ */
+ public PSD unmarshall(XMLStreamReader reader) throws MarshallException {
+
+ try {
+ PSD serviceDefinition = getConcreteModelObject();
+ serviceDefinition.setName(reader.getAttributeValue(null, NAME));
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject modelObject = registry.unmarshall(reader);
+ String name = reader.getName().getLocalPart();
+ if (OPERATION.equals(name)) {
+ serviceDefinition.addOperation((PhysicalOperationDefinition)modelObject);
+ } else {
+ handleExtension(serviceDefinition, reader);
+ }
+ break;
+ case END_ELEMENT:
+ return serviceDefinition;
+
+ }
+ }
+ } catch (XMLStreamException ex) {
+ throw new MarshallException(ex);
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalComponentDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalComponentDefinitionMarshaller.java
new file mode 100644
index 0000000000..08ed890da7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalComponentDefinitionMarshaller.java
@@ -0,0 +1,157 @@
+/*
+ * 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.core.marshaller.extensions.java;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.tuscany.core.marshaller.extensions.AbstractPhysicalComponentDefinitionMarshaller;
+import org.apache.tuscany.core.model.physical.java.JavaPhysicalComponentDefinition;
+import org.apache.tuscany.core.model.physical.java.JavaPhysicalReferenceDefinition;
+import org.apache.tuscany.core.model.physical.java.JavaPhysicalServiceDefinition;
+import org.apache.tuscany.spi.marshaller.MarshallException;
+import org.apache.tuscany.spi.model.Scope;
+
+/**
+ * Marshaller for Java physical component definitions.
+ *
+ * @version $Revision$ $Date: 2007-03-03 16:41:22 +0000 (Sat, 03 Mar
+ * 2007) $
+ */
+public class JavaPhysicalComponentDefinitionMarshaller extends
+ AbstractPhysicalComponentDefinitionMarshaller<JavaPhysicalComponentDefinition> {
+
+ // Instance factory
+ private static final String INSTANCE_FACTORY = "instanceFactory";
+
+ // Scope
+ private static final String SCOPE = "scope";
+
+ // Classloader id
+ private static final String CLASSLOADER_ID = "classLoaderId";
+
+ // QName for the root element
+ private static final QName QNAME =
+ new QName("http://tuscany.apache.org/xmlns/marshaller/java/1.0-SNAPSHOT", "component");
+
+ /**
+ * Gets the qualified name of the XML fragment for the marshalled model
+ * object.
+ *
+ * @return {"http://tuscany.apache.org/xmlns/marshaller/component/java/1.0-SNAPSHOT",
+ * "component"}
+ */
+ @Override
+ protected QName getModelObjectQName() {
+ return QNAME;
+ }
+
+ /**
+ * Retursn the type of the model object.
+ *
+ * @return <code>JavaPhysicalComponentDefinition.class</code>.
+ */
+ @Override
+ protected Class<JavaPhysicalComponentDefinition> getModelObjectType() {
+ return JavaPhysicalComponentDefinition.class;
+ }
+
+ /**
+ * Create the concrete PCD.
+ *
+ * @return An instance of<code>JavaPhysicalComponentDefinition</code>.
+ */
+ @Override
+ protected JavaPhysicalComponentDefinition getConcreteModelObject() {
+ return new JavaPhysicalComponentDefinition();
+ }
+
+ /**
+ * Handles extensions for unmarshalling Java physical component definitions
+ * including the marshalling of base64 encoded instance factory byte code.
+ *
+ * @param componentDefinition Physical component definition.
+ * @param reader Reader from which marshalled data is read.
+ */
+ @Override
+ protected void handleExtension(JavaPhysicalComponentDefinition componentDefinition, XMLStreamReader reader)
+ throws MarshallException {
+
+ try {
+ String name = reader.getName().getLocalPart();
+ reader.next();
+ if (INSTANCE_FACTORY.equals(name)) {
+ byte[] base64ByteCode = reader.getText().getBytes();
+ byte[] byteCode = Base64.decodeBase64(base64ByteCode);
+ componentDefinition.setInstanceFactoryByteCode(byteCode);
+ } else if (SCOPE.equals(name)) {
+ componentDefinition.setScope(new Scope(reader.getText()));
+ } else if (CLASSLOADER_ID.equals(name)) {
+ componentDefinition.setClassLoaderId(new URI(reader.getText()));
+ }
+ } catch (XMLStreamException ex) {
+ throw new MarshallException(ex);
+ } catch (URISyntaxException ex) {
+ throw new MarshallException(ex);
+ }
+
+ }
+
+ /**
+ * Handles a reference.
+ *
+ * @param componentDefinition Component definition.
+ * @param reader XML stream.
+ */
+ protected void handleReference(JavaPhysicalComponentDefinition componentDefinition, XMLStreamReader reader)
+ throws MarshallException {
+ JavaPhysicalReferenceDefinition reference = (JavaPhysicalReferenceDefinition)registry.unmarshall(reader);
+ componentDefinition.addReference(reference);
+ }
+
+ /**
+ * Handles a reference.
+ *
+ * @param componentDefinition Component definition.
+ * @param reader XML stream.
+ */
+ protected void handleService(JavaPhysicalComponentDefinition componentDefinition, XMLStreamReader reader)
+ throws MarshallException {
+ JavaPhysicalServiceDefinition service = (JavaPhysicalServiceDefinition)registry.unmarshall(reader);
+ componentDefinition.addService(service);
+ }
+
+ /**
+ * Handles extensions for marshalling Java physical component definitions
+ * including the marshalling of base64 encoded instance factory byte code.
+ *
+ * @param componentDefinition Physical component definition.
+ * @param reader Writer to which marshalled data is written.
+ */
+ @Override
+ protected void handleExtension(JavaPhysicalComponentDefinition componentDefinition, XMLStreamWriter writer) {
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalReferenceDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalReferenceDefinitionMarshaller.java
new file mode 100644
index 0000000000..3b4a37e903
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalReferenceDefinitionMarshaller.java
@@ -0,0 +1,93 @@
+/*
+ * 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.core.marshaller.extensions.java;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.core.marshaller.extensions.AbstractPhysicalReferenceDefinitionMarshaller;
+import org.apache.tuscany.core.model.physical.java.JavaPhysicalReferenceDefinition;
+
+/**
+ * Marshaller for java physical reference definition.
+ *
+ * @version $Revision$ $Date: 2007-03-03 16:41:22 +0000 (Sat, 03 Mar
+ * 2007) $
+ */
+public class JavaPhysicalReferenceDefinitionMarshaller extends
+ AbstractPhysicalReferenceDefinitionMarshaller<JavaPhysicalReferenceDefinition> {
+
+ // QName for the root element
+ private static final QName QNAME =
+ new QName("http://tuscany.apache.org/xmlns/marshaller/java/1.0-SNAPSHOT", "reference");
+
+ /**
+ * Gets the qualified name of the XML fragment for the marshalled model
+ * object.
+ *
+ * @return {"http://tuscany.apache.org/xmlns/marshaller/reference/java/1.0-SNAPSHOT",
+ * "service"}.
+ */
+ @Override
+ protected QName getModelObjectQName() {
+ return QNAME;
+ }
+
+ /**
+ * Retursn the type of the model object.
+ *
+ * @return <code>JavaPhysicalReferenceDefinition.class</code>.
+ */
+ @Override
+ protected Class<JavaPhysicalReferenceDefinition> getModelObjectType() {
+ return JavaPhysicalReferenceDefinition.class;
+ }
+
+ /**
+ * Create the concrete model object.
+ *
+ * @return An instance of <code>JavaPhysicalReferenceDefinition</code>.
+ */
+ @Override
+ protected JavaPhysicalReferenceDefinition getConcreteModelObject() {
+ return new JavaPhysicalReferenceDefinition();
+ }
+
+ /**
+ * Handles extensions for unmarshalling Java physical references.
+ *
+ * @param modelObject Concrete model object.
+ * @param reader Reader from which marshalled data is read.
+ */
+ @Override
+ protected void handleExtension(JavaPhysicalReferenceDefinition modelObject, XMLStreamReader reader) {
+ }
+
+ /**
+ * Handles extensions for marshalling Java physical references.
+ *
+ * @param modelObject Concrete model object.
+ * @param reader Writer to which marshalled data is written.
+ */
+ @Override
+ protected void handleExtension(JavaPhysicalReferenceDefinition modelObject, XMLStreamWriter writer) {
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalServiceDefinitionMarshaller.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalServiceDefinitionMarshaller.java
new file mode 100644
index 0000000000..ade4d3fd5e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/marshaller/extensions/java/JavaPhysicalServiceDefinitionMarshaller.java
@@ -0,0 +1,93 @@
+/*
+ * 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.core.marshaller.extensions.java;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.core.marshaller.extensions.AbstractPhysicalServiceDefinitionMarshaller;
+import org.apache.tuscany.core.model.physical.java.JavaPhysicalServiceDefinition;
+
+/**
+ * Marshaller for java physical service definition.
+ *
+ * @version $Revision$ $Date: 2007-03-03 16:41:22 +0000 (Sat, 03 Mar
+ * 2007) $
+ */
+public class JavaPhysicalServiceDefinitionMarshaller extends
+ AbstractPhysicalServiceDefinitionMarshaller<JavaPhysicalServiceDefinition> {
+
+ // QName for the root element
+ private static final QName QNAME =
+ new QName("http://tuscany.apache.org/xmlns/marshaller/java/1.0-SNAPSHOT", "service");
+
+ /**
+ * Gets the qualified name of the XML fragment for the marshalled model
+ * object.
+ *
+ * @return {"http://tuscany.apache.org/xmlns/marshaller/reference/java/1.0-SNAPSHOT",
+ * "service"}.
+ */
+ @Override
+ protected QName getModelObjectQName() {
+ return QNAME;
+ }
+
+ /**
+ * Returns the type of the model object.
+ *
+ * @return <code>JavaPhysicalServiceDefinition.class</code>.
+ */
+ @Override
+ protected Class<JavaPhysicalServiceDefinition> getModelObjectType() {
+ return JavaPhysicalServiceDefinition.class;
+ }
+
+ /**
+ * Create the concrete model object.
+ *
+ * @return An instance of <code>JavaPhysicalServiceDefinition</code>.
+ */
+ @Override
+ protected JavaPhysicalServiceDefinition getConcreteModelObject() {
+ return new JavaPhysicalServiceDefinition();
+ }
+
+ /**
+ * Handles extensions for unmarshalling Java service definitions.
+ *
+ * @param modelObject Concrete model object.
+ * @param reader Reader from which marshalled data is read.
+ */
+ @Override
+ protected void handleExtension(JavaPhysicalServiceDefinition modelObject, XMLStreamReader reader) {
+ }
+
+ /**
+ * Handles extensions for marshalling Java service definitions.
+ *
+ * @param modelObject Concrete model object.
+ * @param reader Writer to which marshalled data is written.
+ */
+ @Override
+ protected void handleExtension(JavaPhysicalServiceDefinition modelObject, XMLStreamWriter writer) {
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalComponentDefinition.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalComponentDefinition.java
new file mode 100644
index 0000000000..b0e06f23d9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalComponentDefinition.java
@@ -0,0 +1,93 @@
+/*
+ * 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.core.model.physical.java;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.physical.PhysicalComponentDefinition;
+
+/**
+ * Represents the physical component definition for a Java implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaPhysicalComponentDefinition extends
+ PhysicalComponentDefinition<JavaPhysicalServiceDefinition, JavaPhysicalReferenceDefinition> {
+
+ // The byte code for the instance factory
+ private byte[] instanceFactoryByteCode;
+
+ // Scope
+ private Scope scope;
+
+ // Class loader id
+ private URI classLoaderId;
+
+ /**
+ * Gets the classloader id.
+ * @return Classloader id.
+ */
+ public URI getClassLoaderId() {
+ return classLoaderId;
+ }
+
+ /**
+ * Set the classloader id.
+ * @param classLoaderId Classloader id.
+ */
+ public void setClassLoaderId(URI classLoaderId) {
+ this.classLoaderId = classLoaderId;
+ }
+
+ /**
+ * Gets the scope for the component.
+ * @return The scope for the component.
+ */
+ public Scope getScope() {
+ return scope;
+ }
+
+ /**
+ * Sets the scope for the component.
+ * @param scope The scope for the component.
+ */
+ public void setScope(Scope scope) {
+ this.scope = scope;
+ }
+
+ /**
+ * Gets the byte code for the instance factory.
+ *
+ * @return Byte code for the instance factory.
+ */
+ public byte[] getInstanceFactoryByteCode() {
+ return instanceFactoryByteCode;
+ }
+
+ /**
+ * Sets the byte code for the instance factory.
+ *
+ * @param instanceFactoryByteCode Byte code for the instance factory.
+ */
+ public void setInstanceFactoryByteCode(byte[] instanceFactoryByteCode) {
+ this.instanceFactoryByteCode = instanceFactoryByteCode;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalReferenceDefinition.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalReferenceDefinition.java
new file mode 100644
index 0000000000..51919c6000
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalReferenceDefinition.java
@@ -0,0 +1,31 @@
+/*
+ * 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.core.model.physical.java;
+
+import org.apache.tuscany.spi.model.physical.PhysicalReferenceDefinition;
+
+/**
+ * Models a Java physical reference definition.
+ *
+ * @version $Revision$ $Date: 2007-02-28 06:29:37 +0000 (Wed, 28 Feb
+ * 2007) $
+ */
+public class JavaPhysicalReferenceDefinition extends PhysicalReferenceDefinition {
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalServiceDefinition.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalServiceDefinition.java
new file mode 100644
index 0000000000..06885dfdce
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/model/physical/java/JavaPhysicalServiceDefinition.java
@@ -0,0 +1,31 @@
+/*
+ * 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.core.model.physical.java;
+
+import org.apache.tuscany.spi.model.physical.PhysicalServiceDefinition;
+
+/**
+ * Models a Java physical service definition.
+ *
+ * @version $Revision$ $Date: 2007-02-28 06:29:37 +0000 (Wed, 28 Feb
+ * 2007) $
+ */
+public class JavaPhysicalServiceDefinition extends PhysicalServiceDefinition {
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java
new file mode 100644
index 0000000000..14468061e3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.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.core.monitor;
+
+import java.io.PrintWriter;
+
+import org.apache.tuscany.api.TuscanyException;
+import org.apache.tuscany.api.TuscanyRuntimeException;
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+
+/**
+ * Performs basics formatting of exceptions for JDK logging
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultExceptionFormatter implements ExceptionFormatter {
+
+ public DefaultExceptionFormatter() {
+ }
+
+ public boolean canFormat(Class<?> type) {
+ return Throwable.class.isAssignableFrom(type);
+ }
+
+ public PrintWriter write(PrintWriter writer, Throwable exception) {
+ if (exception instanceof TuscanyException) {
+ TuscanyException e = (TuscanyException) exception;
+ e.appendBaseMessage(writer);
+ } else if (exception instanceof TuscanyRuntimeException) {
+ TuscanyRuntimeException e = (TuscanyRuntimeException) exception;
+ e.appendBaseMessage(writer);
+ }
+ writer.append("\n");
+ return writer;
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java
new file mode 100644
index 0000000000..cf07b0f914
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.monitor;
+
+/**
+ * Exception indicating an invalid log level has been passed.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidLevelException extends IllegalArgumentException {
+ private static final long serialVersionUID = 7767234706427841915L;
+ private final String method;
+ private final String level;
+
+ /**
+ * Constructor specifying the method name and the level affected.
+ *
+ * @param method the name of the method being monitored
+ * @param level the invalid log level value
+ */
+ public InvalidLevelException(String method, String level) {
+ super();
+ this.method = method;
+ this.level = level;
+ }
+
+ /**
+ * Returns the name of the method being monitored.
+ *
+ * @return the name of the method being monitored
+ */
+ public String getMethod() {
+ return method;
+ }
+
+ /**
+ * Returns the invalid log level specified.
+ *
+ * @return the invalid log level that was specified
+ */
+ public String getLevel() {
+ return level;
+ }
+
+ public String getMessage() {
+ return "Invalid level for method " + method + " : " + level;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java
new file mode 100644
index 0000000000..4adff1b0db
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java
@@ -0,0 +1,120 @@
+/*
+ * 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.core.monitor;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+
+/**
+ * A factory for monitors that forwards events to a {@link java.util.logging.Logger Java Logging (JSR47) Logger}.
+ *
+ * @version $Rev$ $Date$
+ * @see java.util.logging
+ */
+@Service(interfaces = {MonitorFactory.class, FormatterRegistry.class})
+public class JavaLoggingMonitorFactory extends ProxyMonitorFactory {
+
+ /**
+ * Construct a MonitorFactory that will monitor the specified methods at the specified levels and generate messages
+ * using java.util.logging.
+ * <p/>
+ * The supplied Properties can be used to specify custom log levels for specific monitor methods. The key should be
+ * the method name in form returned by <code>Class.getName() + '#' + Method.getName()</code> and the value the log
+ * level to use as defined by {@link java.util.logging.Level}.
+ *
+ * @param levels definition of custom levels for specific monitored methods, may be null or empty.
+ * @param defaultLevel the default log level to use
+ * @param bundleName the name of a resource bundle that will be passed to the logger
+ * @see java.util.logging.Logger
+ */
+ public JavaLoggingMonitorFactory(Properties levels, Level defaultLevel, String bundleName) {
+ Map<String, Object> configProperties = new HashMap<String, Object>();
+ configProperties.put("levels", levels);
+ configProperties.put("defaultLevel", defaultLevel);
+ configProperties.put("bundleName", bundleName);
+ initInternal(configProperties);
+ }
+
+ /**
+ * Constructs a MonitorFactory that needs to be subsequently configured via a call to {@link #initialize}.
+ */
+ public JavaLoggingMonitorFactory() {
+ }
+
+ protected <T> InvocationHandler createInvocationHandler(Class<T> monitorInterface,
+ Map<String, Level> levels) {
+ ResourceBundle bundle = locateBundle(monitorInterface, bundleName);
+ Logger logger = Logger.getLogger(monitorInterface.getName());
+ return new LoggingHandler(logger, levels, bundle);
+ }
+
+ private class LoggingHandler implements InvocationHandler {
+ private final Logger logger;
+ private final Map<String, Level> methodLevels;
+ private final ResourceBundle bundle;
+
+ public LoggingHandler(Logger logger,
+ Map<String, Level> methodLevels,
+ ResourceBundle bundle
+ ) {
+ this.logger = logger;
+ this.methodLevels = methodLevels;
+ this.bundle = bundle;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ String sourceMethod = method.getName();
+ Level level = methodLevels.get(sourceMethod);
+ if (level != null && logger.isLoggable(level)) {
+ // construct the key for the resource bundle
+ String className = logger.getName();
+ String key = className + '#' + sourceMethod;
+
+ LogRecord logRecord = new LogRecord(level, key);
+ logRecord.setLoggerName(className);
+ logRecord.setSourceClassName(className);
+ logRecord.setSourceMethodName(sourceMethod);
+ logRecord.setParameters(args);
+ if (args != null) {
+ for (Object o : args) {
+ if (o instanceof Throwable) {
+ logRecord.setMessage(formatException((Throwable) o));
+ break;
+ }
+ }
+ }
+ logRecord.setResourceBundle(bundle);
+ logger.log(logRecord);
+ }
+ return null;
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java
new file mode 100644
index 0000000000..92224d469f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.monitor;
+
+import org.apache.tuscany.host.MonitorFactory;
+
+import java.util.Map;
+
+/**
+ * Helper for creating MonitorFactory instances.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+
+public final class MonitorFactoryUtil {
+ /**
+ * Hide the constructor
+ */
+ private MonitorFactoryUtil() {
+ }
+
+ /**
+ * Creates a MonitorFactory instance of the specified type.
+ * @param name fully qualified classname of the desired MonitorFactory type
+ * @param props collection of initialization properties
+ * @return a configured MonitorFactory instance, or null if the factory could not be instantiated.
+ */
+ @SuppressWarnings("unchecked")
+ public static MonitorFactory createMonitorFactory(String name, Map<String, Object> props) {
+ Class<? extends MonitorFactory> clazz;
+ try {
+ clazz = (Class<? extends MonitorFactory>) Class.forName(name);
+ } catch (ClassNotFoundException cnfe) {
+ return null;
+ } catch (ClassCastException cce) {
+ return null;
+ }
+
+ return createMonitorFactory(clazz, props);
+ }
+
+ /**
+ * Creates a MonitorFactory instance of the specified type.
+ * @param mfc class of the desired MonitorFactory type
+ * @param props collection of initialization properties
+ * @return a configured MonitorFactory instance, or null if the factory could not be instantiated.
+ */
+ public static MonitorFactory createMonitorFactory(Class<? extends MonitorFactory> mfc, Map<String, Object> props) {
+ MonitorFactory mf;
+ try {
+ mf = mfc.newInstance();
+ mf.initialize(props);
+ } catch (InstantiationException e) {
+ throw new AssertionError(e);
+ } catch (IllegalAccessException e) {
+ throw new AssertionError(e);
+ }
+ // allow IllegalArgumentException to propogate out
+
+ return mf;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java
new file mode 100644
index 0000000000..46c52e38f6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.core.monitor;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+
+/**
+ * Implementation of a {@link MonitorFactory} that produces implementations that simply return.
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class NullMonitorFactory implements MonitorFactory {
+
+ /**
+ * Singleton hander that does nothing.
+ */
+ private static final InvocationHandler NULL_MONITOR = new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args) {
+ return null;
+ }
+ };
+
+ public void initialize(Map<String, Object> configProperties) {
+ }
+
+ public <T> T getMonitor(Class<T> monitorInterface) {
+ /*
+ * This uses a reflection proxy to implement the monitor interface which
+ * is a simple but perhaps not very performant solution. Performance
+ * might be improved by code generating an implementation with empty methods.
+ */
+ return monitorInterface.cast(
+ Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class<?>[]{monitorInterface}, NULL_MONITOR));
+ }
+
+ public void register(ExceptionFormatter formatter) {
+
+ }
+
+ public void unregister(ExceptionFormatter formatter) {
+
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/ProxyMonitorFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/ProxyMonitorFactory.java
new file mode 100644
index 0000000000..d9ca9e6cfc
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/monitor/ProxyMonitorFactory.java
@@ -0,0 +1,234 @@
+/*
+ * 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.core.monitor;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.HashMap;
+import java.util.ResourceBundle;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+import org.apache.tuscany.api.annotation.LogLevel;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class ProxyMonitorFactory implements MonitorFactory, FormatterRegistry {
+ protected String bundleName;
+ protected final List<ExceptionFormatter> formatters = new ArrayList<ExceptionFormatter>();
+ protected final ExceptionFormatter defaultFormatter = new DefaultExceptionFormatter();
+ protected Level defaultLevel;
+ protected Map<String, Level> levels;
+ private final Map<Class<?>, WeakReference<?>> proxies = new WeakHashMap<Class<?>, WeakReference<?>>();
+
+ public void initialize(Map<String, Object> configProperties) {
+ if (configProperties == null) {
+ return;
+ }
+ initInternal(configProperties);
+ }
+
+ protected void initInternal(Map<String, Object> configProperties) {
+ try {
+ this.defaultLevel = (Level) configProperties.get("defaultLevel");
+ this.bundleName = (String) configProperties.get("bundleName");
+ Properties levels = (Properties) configProperties.get("levels");
+
+ this.levels = new HashMap<String, Level>();
+ if (levels != null) {
+ for (Map.Entry<Object, Object> entry : levels.entrySet()) {
+ String method = (String) entry.getKey();
+ String level = (String) entry.getValue();
+ try {
+ this.levels.put(method, Level.parse(level));
+ } catch (IllegalArgumentException e) {
+ throw new InvalidLevelException(method, level);
+ }
+ }
+ }
+ } catch (ClassCastException cce) {
+ throw new IllegalArgumentException(cce.getLocalizedMessage());
+ }
+ }
+
+ public synchronized <T> T getMonitor(Class<T> monitorInterface) {
+ T proxy = getCachedMonitor(monitorInterface);
+ if (proxy == null) {
+ proxy = createMonitor(monitorInterface);
+ proxies.put(monitorInterface, new WeakReference<T>(proxy));
+ }
+ return proxy;
+ }
+
+ protected <T> T getCachedMonitor(Class<T> monitorInterface) {
+ WeakReference<?> ref = proxies.get(monitorInterface);
+ return (ref != null) ? monitorInterface.cast(ref.get()) : null;
+ }
+
+ protected <T> T createMonitor(Class<T> monitorInterface) {
+ String className = monitorInterface.getName();
+ Method[] methods = monitorInterface.getMethods();
+ Map<String, Level> levels = new HashMap<String, Level>(methods.length);
+ for (Method method : methods) {
+ String key = className + '#' + method.getName();
+ Level level = null;
+ if (this.levels != null) {
+ this.levels.get(key);
+ }
+ // if not specified the in config properties, look for an annotation on the method
+ if (level == null) {
+ LogLevel annotation = method.getAnnotation(LogLevel.class);
+ if (annotation != null && annotation.value() != null) {
+ try {
+ level = Level.parse(annotation.value());
+ } catch (IllegalArgumentException e) {
+ // bad value, just use the default
+ level = defaultLevel;
+ }
+ }
+ }
+ if (level == null) {
+ level = defaultLevel;
+ }
+ levels.put(method.getName(), level);
+ }
+
+ InvocationHandler handler = createInvocationHandler(monitorInterface, levels);
+ Object proxy = Proxy.newProxyInstance(monitorInterface.getClassLoader(),
+ new Class<?>[]{monitorInterface},
+ handler);
+ return monitorInterface.cast(proxy);
+ }
+
+ protected <T> ResourceBundle locateBundle(Class<T> monitorInterface, String bundleName) {
+ Locale locale = Locale.getDefault();
+ ClassLoader cl = monitorInterface.getClassLoader();
+ String packageName = monitorInterface.getPackage().getName();
+ while (true) {
+ try {
+ return ResourceBundle.getBundle(packageName + '.' + bundleName, locale, cl);
+ } catch (MissingResourceException e) {
+ //ok
+ }
+ int index = packageName.lastIndexOf('.');
+ if (index == -1) {
+ break;
+ }
+ packageName = packageName.substring(0, index);
+ }
+ try {
+ return ResourceBundle.getBundle(bundleName, locale, cl);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void register(ExceptionFormatter formatter) {
+ formatters.add(formatter);
+ }
+
+ public void unregister(ExceptionFormatter formatter) {
+ formatters.remove(formatter);
+ }
+
+ protected abstract <T> InvocationHandler createInvocationHandler(Class<T> monitorInterface,
+ Map<String, Level> levels);
+
+ protected String formatException(Throwable e) {
+ ExceptionFormatter formatter = defaultFormatter;
+ for (ExceptionFormatter candidate : formatters) {
+ if (candidate.canFormat(e.getClass())) {
+ formatter = candidate;
+ break;
+ }
+ }
+ StringWriter writer = new StringWriter();
+ PrintWriter pw = new PrintWriter(writer);
+ formatter.write(pw, e);
+ format(pw, e);
+ pw.close();
+ return writer.toString();
+ }
+
+ protected void format(PrintWriter writer, Throwable throwable) {
+ writer.println(throwable.getClass().getName());
+ StackTraceElement[] trace = throwable.getStackTrace();
+ for (StackTraceElement aTrace : trace) {
+ writer.println("\tat " + aTrace);
+ }
+ Throwable ourCause = throwable.getCause();
+
+ if (ourCause != null) {
+ printStackTraceAsCause(writer, ourCause, trace);
+ }
+ }
+
+ protected void printStackTraceAsCause(PrintWriter pw,
+ Throwable throwable,
+ StackTraceElement[] causedTrace) {
+
+ // Compute number of frames in common between this and caused
+ StackTraceElement[] trace = throwable.getStackTrace();
+ int m = trace.length - 1;
+ int n = causedTrace.length - 1;
+ while (m >= 0 && n >= 0 && trace[m].equals(causedTrace[n])) {
+ m--;
+ n--;
+ }
+ int framesInCommon = trace.length - 1 - m;
+
+ pw.println("Caused by: " + throwable.getClass().getName());
+
+ ExceptionFormatter formatter = defaultFormatter;
+ for (ExceptionFormatter candidate : formatters) {
+ if (candidate.canFormat(throwable.getClass())) {
+ formatter = candidate;
+ break;
+ }
+ }
+ formatter.write(pw, throwable);
+
+ for (int i = 0; i <= m; i++) {
+ pw.println("\tat " + trace[i]);
+ }
+ if (framesInCommon != 0) {
+ pw.println("\t... " + framesInCommon + " more");
+ }
+
+ // Recurse if we have a cause
+ Throwable ourCause = throwable.getCause();
+ if (ourCause != null) {
+ printStackTraceAsCause(pw, ourCause, trace);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java
new file mode 100644
index 0000000000..5ea24e4c9b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java
@@ -0,0 +1,167 @@
+/*
+ * 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.core.policy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.model.Intent;
+import org.apache.tuscany.spi.model.IntentName;
+import org.apache.tuscany.spi.policy.IntentRegistry;
+
+/**
+ * The default implementation of a data intent registry
+ */
+public class IntentRegistryImpl implements IntentRegistry {
+ private final Map<IntentName, IntentEntry> intentRepo = new HashMap<IntentName, IntentEntry>();
+
+ public Collection<IntentName> getQualifiedIntents(final IntentName qualifiable, final QName artifact) {
+ List<IntentName> result = new ArrayList<IntentName>();
+ for (IntentName intentName : intentRepo.keySet()) {
+ if (intentRepo.get(intentName).getAppliedArtifacts().contains(artifact)
+ && PolicyHelper.isQualifiedIntentFor(intentName, qualifiable, true)) {
+ result.add(intentName);
+ }
+ }
+ return result;
+ }
+
+ public Collection<IntentName> inlineProfileIntent(final Collection<IntentName> intentNameList,
+ final QName artifact) {
+
+ return getConcretIntentsInternal(intentNameList, artifact);
+ }
+
+ private Collection<IntentName> getConcretIntentsInternal(final Collection<IntentName> intentNameList,
+ QName artifact) {
+ List<IntentName> result = new ArrayList<IntentName>();
+ for (IntentName intentName : intentNameList) {
+ IntentEntry intentEntry = intentRepo.get(intentName);
+ if (!intentEntry.isProfileIntent()) {
+ if (intentEntry.getAppliedArtifacts().contains(artifact)) {
+ result.add(intentEntry.getName());
+ }
+ } else {
+ result.addAll(getConcretIntentsInternal(intentEntry.getRequriedIntents(), artifact));
+ }
+ }
+ return result;
+ }
+
+ public boolean isApplicable(IntentName intentName, QName artifact) {
+ if (intentRepo.containsKey(intentName)) {
+ return intentRepo.get(intentName).getAppliedArtifacts().contains(artifact);
+ }
+ return false;
+ }
+
+ public void register(Intent intent) {
+
+ IntentEntry entry = new IntentEntry(intent);
+ // if the qualified intents have been registered, make the intent qualifiable(unqualified)
+ if (!getQualifiedIntents(intent.getName()).isEmpty()) {
+ entry.setQualified(false);
+ }
+ intentRepo.put(intent.getName(), entry);
+ List<IntentName> qualifiables = getAllQualifiableIntent(intent.getName());
+ // set qualifiable intent of this intent unqualified
+ for (IntentName qualifiable : qualifiables) {
+ IntentEntry qualifiableEntry = intentRepo.get(qualifiable);
+ qualifiableEntry.setQualified(false);
+ for (QName artifact : intent.getAppliedArtifacts()) {
+ qualifiableEntry.addAppliedArtifacts(artifact);
+ }
+ }
+ }
+
+ public void unRegister(Intent intent) {
+ if (intentRepo.containsKey(intent.getName())) {
+ IntentEntry intentEntry = intentRepo.get(intent.getName());
+ List<QName> appliedArtifacts = intent.getAppliedArtifacts();
+ for (QName artifact : appliedArtifacts) {
+ if (intentEntry.getAppliedArtifacts().contains(artifact)) {
+ intentEntry.removeappliedArtifact(artifact);
+ }
+ }
+ if (intentEntry.getAppliedArtifacts().isEmpty()) {
+ intentRepo.remove(intent.getName());
+ }
+ }
+ }
+
+ public boolean isQualifiedIntent(IntentName name) {
+ IntentEntry intentEntry = intentRepo.get(name);
+ return intentEntry.isQualified();
+ }
+
+ private List<IntentName> getQualifiedIntents(final IntentName qualifiable) {
+ List<IntentName> result = new ArrayList<IntentName>();
+ for (IntentName intentName : intentRepo.keySet()) {
+ if (PolicyHelper.isQualifiedIntentFor(intentName, qualifiable, true)) {
+ result.add(intentName);
+ }
+ }
+ return result;
+ }
+
+ private List<IntentName> getAllQualifiableIntent(final IntentName qualified) {
+
+ List<IntentName> result = new ArrayList<IntentName>();
+ for (IntentName intentName : intentRepo.keySet()) {
+ if (PolicyHelper.isQualifiedIntentFor(qualified, intentName, false)) {
+ result.add(intentName);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Wrapper class for intent used internally
+ */
+ private static final class IntentEntry extends Intent {
+
+ /**
+ * Whether this intent is qualified, defaults to true
+ */
+ private boolean isQualified = true;
+
+ private IntentEntry(Intent intent) {
+ super(intent.getName(), intent.getDescription());
+ appliedArtifacts.addAll(intent.getAppliedArtifacts());
+ requriedIntents.addAll(intent.getRequriedIntents());
+ }
+
+ public boolean isQualified() {
+ return isQualified;
+ }
+
+ public void setQualified(boolean isQualified) {
+ this.isQualified = isQualified;
+ }
+
+ public void removeappliedArtifact(QName artifact) {
+ appliedArtifacts.remove(artifact);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java
new file mode 100644
index 0000000000..9c874b5610
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java
@@ -0,0 +1,59 @@
+/*
+ * 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.core.policy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.policy.PolicyBuilderRegistry;
+import org.apache.tuscany.spi.policy.SourcePolicyBuilder;
+import org.apache.tuscany.spi.policy.TargetPolicyBuilder;
+
+/**
+ * The default policy builder
+ *
+ * @version $Rev$ $Date$
+ * @deprecated
+ */
+public class PolicyBuilderRegistryImpl implements PolicyBuilderRegistry {
+
+ private final List<List<SourcePolicyBuilder>> sourceBuilders;
+ private final List<List<TargetPolicyBuilder>> targetBuilders;
+
+ public PolicyBuilderRegistryImpl() {
+ sourceBuilders = new ArrayList<List<SourcePolicyBuilder>>();
+ targetBuilders = new ArrayList<List<TargetPolicyBuilder>>();
+ for (int i = 0; i <= FINAL; i++) {
+ sourceBuilders.add(new ArrayList<SourcePolicyBuilder>());
+ targetBuilders.add(new ArrayList<TargetPolicyBuilder>());
+ }
+ }
+
+ public void registerTargetBuilder(int phase, TargetPolicyBuilder builder) {
+ assert INITIAL <= phase && phase <= FINAL : "Illegal phase";
+ targetBuilders.get(phase).add(builder);
+ }
+
+ public void registerSourceBuilder(int phase, SourcePolicyBuilder builder) {
+ assert INITIAL <= phase && phase <= FINAL : "Illegal phase";
+ sourceBuilders.get(phase).add(builder);
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java
new file mode 100644
index 0000000000..308e43c038
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java
@@ -0,0 +1,297 @@
+/*
+ * 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.core.policy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.model.IntentMap;
+import org.apache.tuscany.spi.model.IntentName;
+import org.apache.tuscany.spi.model.PolicyContentModel;
+import org.apache.tuscany.spi.model.PolicyModel;
+import org.apache.tuscany.spi.model.PolicySet;
+import org.apache.tuscany.spi.model.PolicySetReference;
+import org.apache.tuscany.spi.model.Qualifier;
+import org.apache.tuscany.spi.policy.IntentRegistry;
+import org.apache.tuscany.spi.policy.PolicyEngine;
+import org.apache.tuscany.spi.policy.PolicySetContainer;
+import org.apache.tuscany.spi.policy.SCATypeManager;
+
+/**
+ * Default implementation of a polciy engine
+ */
+public class PolicyEngineImpl implements PolicyEngine {
+ private final IntentRegistry intentRegistry;
+ private final PolicySetContainer policySetContainer;
+ private final SCATypeManager scaTypeManager;
+
+ public PolicyEngineImpl(IntentRegistry intentRegistry,
+ PolicySetContainer policySetContainer,
+ SCATypeManager scaTypeManager) {
+ this.intentRegistry = intentRegistry;
+ this.policySetContainer = policySetContainer;
+ this.scaTypeManager = scaTypeManager;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Collection<PolicyModel> getPolicy(final IntentName[] requires,
+ final QName[] policySetNames,
+ final QName artifactType) {
+ if (requires == null || requires.length == 0) {
+ return Collections.EMPTY_LIST;
+ }
+ Collection<PolicyModel> result = new ArrayList<PolicyModel>();
+ Collection<IntentName> requiredIntents = java.util.Arrays.asList(requires);
+ Collection<IntentName> matchings;
+
+ //handle profile intents
+ requiredIntents = intentRegistry.inlineProfileIntent(requiredIntents, artifactType);
+ //
+ if (policySetNames != null && policySetNames.length != 0) {
+ Collection<PolicySet> explicitPolicySet = getExplicitPolicySet(policySetNames);
+ matchings = calculateExplicitPolicySet(requiredIntents, explicitPolicySet, artifactType, result);
+ //remove satisfied intent
+ requiredIntents.removeAll(matchings);
+ }
+ //
+ if (requiredIntents.size() > 0) {
+ matchings = findingAdditionalMatching(requiredIntents, artifactType, result);
+ requiredIntents.removeAll(matchings);
+ }
+ //If no collection of policySets covers all required intents, the configuration is not valid.
+ if (requiredIntents.size() > 0) {
+ //TODO
+ }
+ return result;
+ }
+
+
+ private boolean introspectPolicySet(PolicySet policySet, IntentName intent, QName artifactType,
+ Collection<PolicyModel> matchings) {
+ Collection<QName> appliedArtifacts = policySet.getAppliedArtifacts();
+ boolean provide = false;
+ for (QName name : appliedArtifacts) {
+ if (this.scaTypeManager.isTypeOf(artifactType, name)) {
+ provide = true;
+ break;
+ }
+ }
+ if (!provide) {
+ return false;
+ }
+ //1. The required intent matches a provides intent in a policySet exactly.
+ if (policySet.getProvideIntents().contains(intent)) {
+ if (intentRegistry.isQualifiedIntent(intent)) {
+ addMatching(matchings, policySet);
+ } else {
+ Collection<IntentMap> intentMaps = policySet.getIntentMaps();
+ provide = searchIntentMaps(intent, intent, matchings, intentMaps);
+ if (provide) {
+ return true;
+ }
+ }
+ } else if (provideAbstract(intent, policySet.getProvideIntents())) {
+ // 2. The provides intent is a parent (e.g. prefix) of the required intent (in this case the policySet must
+ // have an intentMap entry for the requested qualifier)
+ Collection<IntentMap> intentMaps = policySet.getIntentMaps();
+ IntentName satisfiedIntent = getSatisfiedIntent(intent, policySet.getProvideIntents());
+ provide = searchIntentMaps(intent, satisfiedIntent, matchings, intentMaps);
+ if (provide) {
+ return true;
+ }
+ } else if (provideQualifier(intent, policySet.getProvideIntents())) {
+ //3. The provides intent is more qualified than the required intent
+ if (intentRegistry.isQualifiedIntent(intent)) {
+ addMatching(matchings, policySet);
+ } else {
+ //TODO
+ }
+ }
+
+ //handle PolicySetReference
+ Collection<PolicySetReference> policySetReferences = policySet.getPolicySetReferences();
+ for (PolicySetReference reference : policySetReferences) {
+ PolicySet referencedPolicySet = policySetContainer.getPolicySet(reference.getReference());
+ if (introspectPolicySet(referencedPolicySet, intent, artifactType, matchings)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void addMatching(Collection<PolicyModel> matching, PolicyContentModel policy) {
+ if (!policy.getWsPolicyAttachments().isEmpty()) {
+ matching.addAll(policy.getWsPolicyAttachments());
+ }
+ if (!policy.getPolicyExtensions().isEmpty()) {
+ matching.addAll(policy.getPolicyExtensions());
+ }
+ }
+
+ private boolean searchIntentMaps(IntentName require,
+ IntentName satisfiedIntent,
+ Collection<PolicyModel> matchings,
+ Collection<IntentMap> intentMaps) {
+ String qualifierName = getQualifierName(require, satisfiedIntent, intentMaps);
+ for (IntentMap intentMap : intentMaps) {
+ if (intentMap.getProvideIntents().contains(qualifierName)) {
+ Collection<Qualifier> qualifiers = intentMap.getQualifiers();
+ for (Qualifier qualifier : qualifiers) {
+ String nextQualifier = getNextQualifier(require, satisfiedIntent, intentMap);
+ if (qualifier.getName().equals(nextQualifier)) {
+ if (intentRegistry
+ .isQualifiedIntent(new IntentName(satisfiedIntent.toString() + "/" + nextQualifier))) {
+ addMatching(matchings, qualifier);
+ return true;
+ } else {
+ require = new IntentName(require.toString() + "/" + intentMap.getDefaultProvideIntent());
+ satisfiedIntent = new IntentName(satisfiedIntent.toString() + "/" + qualifierName);
+ intentMaps = new ArrayList<IntentMap>(0);
+ intentMaps.add(qualifier.getIntentMap());
+ searchIntentMaps(require, satisfiedIntent, matchings, intentMaps);
+ }
+ break;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private String getQualifierName(IntentName require, IntentName satisfiedIntent, Collection<IntentMap> intentMaps) {
+ String[] requrieQualifiers = require.getQualifiedNames();
+ String[] satisfiedQualifiers = satisfiedIntent.getQualifiedNames();
+ if (requrieQualifiers.length == satisfiedQualifiers.length) {
+ return requrieQualifiers[requrieQualifiers.length - 1];
+ } else if (requrieQualifiers.length > satisfiedQualifiers.length) {
+ return satisfiedQualifiers[satisfiedQualifiers.length - 1];
+ }
+ //TODO raise exception
+ return null;
+ }
+
+ private String getNextQualifier(IntentName require, IntentName satisfiedIntent, IntentMap intentMap) {
+ String[] requrieQualifiers = require.getQualifiedNames();
+ String[] satisfiedQualifiers = satisfiedIntent.getQualifiedNames();
+ if (requrieQualifiers.length > satisfiedQualifiers.length) {
+ return requrieQualifiers[satisfiedQualifiers.length];
+ } else {
+ return intentMap.getDefaultProvideIntent();
+ }
+ }
+
+ private IntentName getSatisfiedIntent(IntentName require, Collection<IntentName> provides) {
+ for (IntentName name : provides) {
+ if (PolicyHelper.isQualifiedIntentFor(require, name, true)) {
+ return name;
+ }
+ }
+ //TODO raise exception
+ return null;
+ }
+
+ private boolean provideAbstract(IntentName require, Collection<IntentName> provides) {
+ for (IntentName name : provides) {
+ if (PolicyHelper.isQualifiedIntentFor(require, name, true)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean provideQualifier(IntentName require, Collection<IntentName> provides) {
+ for (IntentName name : provides) {
+ if (PolicyHelper.isQualifiedIntentFor(name, require, true)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Collection<PolicySet> getExplicitPolicySet(QName[] policySetNames) {
+ Collection<PolicySet> result = new ArrayList<PolicySet>();
+ for (QName policySetName : policySetNames) {
+ PolicySet set = policySetContainer.getPolicySet(policySetName);
+ if (set != null) {
+ result.add(set);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Step C. Calculate the list of explicitly specified policySets that apply to the target element as follows: 1.
+ * Start with the list of policySets specified in the element's policySet attribute. 2. If any of these explicitly
+ * listed policySets has an XPath expression in its appliesTo attribute that does not match the target element
+ * (binding or implementation) then the composite is invalid. It does not match if the XPath returns a result set
+ * that corresponds to XPath false. For example, a policySet could have appliesTo=”binding.ws/soaphttp”. This would
+ * return false if the target element is a <binding.jms…/> element. 3. Include the values of policySet attributes
+ * from ancestor elements. 4. Remove any policySet where the XPath expression in that policySet’s appliesTo
+ * attribute does not match the target element.
+ * <p/>
+ *
+ * @param requires
+ * @param policies
+ * @return intent names was satisfied by this step.
+ */
+ private Collection<IntentName> calculateExplicitPolicySet(Collection<IntentName> requires,
+ Collection<PolicySet> policies,
+ QName artifactType,
+ Collection<PolicyModel> matchings) {
+ Collection<IntentName> satisfied = new ArrayList<IntentName>();
+ for (IntentName intent : requires) {
+ for (PolicySet policySet : policies) {
+ if (introspectPolicySet(policySet, intent, artifactType, matchings)) {
+ satisfied.add(intent);
+ }
+ }
+ }
+ return satisfied;
+ }
+
+ /**
+ * * The remaining required intents, if any, are provided by finding additional matching policySets within the SCA
+ * system. E. Choose the smallest collection of these policySets that match all remaining required intents. A
+ * policySet matches a required intent if any of the following are true: 1. The required intent matches a provides
+ * intent in a policySet exactly. 2. The provides intent is a parent (e.g. prefix) of the required intent (in this
+ * case the policySet must have an intentMap entry for the requested qualifier) 3. The provides intent is more
+ * qualified than the required intent All intents should now be satisfied.
+ *
+ * @param remainings
+ * @param artifactType
+ * @param matchings
+ */
+ private Collection<IntentName> findingAdditionalMatching(final Collection<IntentName> remainings,
+ QName artifactType,
+ Collection<PolicyModel> matchings) {
+ Collection<IntentName> satisfied = new ArrayList<IntentName>();
+ Collection<PolicySet> policies = this.policySetContainer.getAllPolicySet();
+ for (IntentName intent : remainings) {
+ for (PolicySet policySet : policies) {
+ if (introspectPolicySet(policySet, intent, artifactType, matchings)) {
+ satisfied.add(intent);
+ }
+ }
+ }
+ return satisfied;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java
new file mode 100644
index 0000000000..50c94aaf13
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.policy;
+
+import org.apache.tuscany.spi.model.IntentName;
+
+/**
+ * Contains utility methods for dealing with policies
+ */
+public final class PolicyHelper {
+
+ private PolicyHelper() {
+ }
+
+ /**
+ * Whether <code>qualified</code> is qualified intent for <code>qualifiable</code>
+ * <p/>
+ * For example: sec.confidentiality/message is direct qualifier for sec.confidentiality.
+ * sec.confidentiality/message/body is qualifier for sec.confidentiality, but not a direct qualifier
+ *
+ * @param qualified qualified intent name
+ * @param qualifiable qualifiable intent name
+ * @param direct indicate whether to expect <code>qualified</code> is direct qualified intent for
+ * <code>qualifiable</code>
+ * @return whether <code>qualified</code> is qualified intent for <code>qualifiable</code>
+ */
+ public static boolean isQualifiedIntentFor(final IntentName qualified,
+ final IntentName qualifiable,
+ boolean direct) {
+ if (qualified.equals(qualifiable) || !qualified.getDomain().equals(qualifiable.getDomain())) {
+ return false;
+ }
+ boolean result = true;
+ String[] shortArray = qualifiable.getQualifiedNames();
+ String[] longArray = qualified.getQualifiedNames();
+ if (longArray.length - shortArray.length < 1 && !direct) {
+ return false;
+ } else if (direct && longArray.length - shortArray.length != 1) {
+ return false;
+ }
+ for (int i = 0; i < shortArray.length; i++) {
+ if (!shortArray[i].equals(longArray[i])) {
+ result = false;
+ break;
+ }
+ }
+ return result;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java
new file mode 100644
index 0000000000..8ed7e8adf6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java
@@ -0,0 +1,194 @@
+/*
+ * 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.core.property;
+
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Map;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.loader.InvalidValueException;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+
+import org.apache.tuscany.core.databinding.xml.InputStream2Node;
+
+/**
+ * The property factory backed by the DataBindingframework
+ */
+public final class PropertyHelper {
+
+ private static final XPathFactory FACTORY = XPathFactory.newInstance();
+
+ private PropertyHelper() {
+ }
+
+ public static Document evaluate(NamespaceContext nsContext, Node node, String xPathExpression)
+ throws XPathExpressionException, ParserConfigurationException {
+ XPath path = FACTORY.newXPath();
+ if (nsContext != null) {
+ path.setNamespaceContext(nsContext);
+ } else {
+ path.setNamespaceContext(new DOMNamespeceContext(node));
+ }
+ XPathExpression expression = path.compile(xPathExpression);
+ Node result = (Node) expression.evaluate(node, XPathConstants.NODE);
+ if (result == null) {
+ return null;
+ }
+
+ // TODO: How to wrap the result into a Document?
+ Document document = DOMHelper.newDocument();
+ if (result instanceof Document) {
+ return document;
+ } else {
+ document.appendChild(document.importNode(result, true));
+ return document;
+ }
+ }
+
+ public static Document loadFromFile(String file, DeploymentContext deploymentContext)
+ throws LoaderException {
+ try {
+ URI uri = URI.create(file);
+ URL url = null;
+ if (!uri.isAbsolute()) {
+ url = deploymentContext.getClassLoader().getResource(file);
+ } else {
+ url = uri.toURL();
+ }
+ InputStream is = url.openStream();
+ try {
+ InputStream2Node transformer = new InputStream2Node();
+ return (Document) transformer.transform(is, null);
+ } finally {
+ is.close();
+ }
+ } catch (Exception e) {
+ throw new LoaderException(e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void processProperties(CompositeComponentType<?, ?, Property<?>> parent,
+ ComponentDefinition<? extends Implementation<?>> componentDefinition,
+ DeploymentContext deploymentContext) throws LoaderException {
+ Map<String, PropertyValue<?>> propertyValues = componentDefinition.getPropertyValues();
+
+ for (PropertyValue propValue : propertyValues.values()) {
+ Document node = propValue.getValue();
+ String source = propValue.getSource();
+ String file = propValue.getFile();
+ if (source != null) {
+ try {
+ // $<name>/...
+ int index = source.indexOf('/');
+ if (index == -1) {
+ // Tolerating $prop
+ source = source + "/";
+ index = source.length() - 1;
+ }
+ if (source.charAt(0) == '$') {
+ String name = source.substring(1, index);
+ Property<?> compositeProp = parent.getProperties().get(name);
+ if (compositeProp == null) {
+ throw new InvalidValueException("Source cannot be resolved to a composite property");
+ }
+ Document document = compositeProp.getDefaultValue();
+ // Adding /value because the document root is "value"
+ String path = source.substring(index);
+ String xpath = null;
+ if ("/".equals(path)) {
+ // trailing / is not legal for xpath
+ xpath = "/value";
+ } else {
+ xpath = "/value" + path;
+ }
+
+ // FIXME: How to deal with namespaces?
+ node = evaluate(null, document, xpath);
+ if (node != null) {
+ propValue.setValue(node);
+ }
+ /*Property<?> prop =
+ (Property<?>)componentDefinition.getImplementation().getComponentType()
+ .getProperties().get(propValue.getName());
+ propValue
+ .setValueFactory(new SimplePropertyObjectFactory(prop, propValue.getValue()));*/
+ } else {
+ throw new InvalidValueException("Source has an invalid value");
+ }
+ } catch (Exception e) {
+ throw new LoaderException(e);
+ }
+ } else if (file != null) {
+ node = loadFromFile(propValue.getFile(), deploymentContext);
+ propValue.setValue(node);
+ Property<?> prop =
+ (Property<?>) componentDefinition.getImplementation().getComponentType().getProperties()
+ .get(propValue.getName());
+ propValue.setValueFactory(new SimplePropertyObjectFactory(prop, propValue.getValue()));
+ }
+ }
+ }
+
+ private static class DOMNamespeceContext implements NamespaceContext {
+ private Node node;
+
+ /**
+ * @param node
+ */
+ public DOMNamespeceContext(Node node) {
+ super();
+ this.node = node;
+ }
+
+ public String getNamespaceURI(String prefix) {
+ return node.lookupNamespaceURI(prefix);
+ }
+
+ public String getPrefix(String namespaceURI) {
+ return node.lookupPrefix(namespaceURI);
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ return null;
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java
new file mode 100644
index 0000000000..8419bc1eba
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java
@@ -0,0 +1,109 @@
+/*
+ * 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.core.property;
+
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Node;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Scope;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.model.ElementInfo;
+import org.apache.tuscany.spi.model.TypeInfo;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.PropertyValue;
+
+import org.apache.tuscany.core.databinding.xml.DOMDataBinding;
+
+@Service(PropertyObjectFactory.class)
+@Scope("COMPOSITE")
+public class PropertyObjectFactoryImpl implements PropertyObjectFactory {
+ private DataBindingRegistry registry;
+ private Mediator mediator;
+
+ public PropertyObjectFactoryImpl() {
+ }
+
+ @Constructor
+ public PropertyObjectFactoryImpl(@Reference DataBindingRegistry registry, @Reference Mediator mediator) {
+ super();
+ this.registry = registry;
+ this.mediator = mediator;
+ }
+
+ public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value) {
+ if (mediator == null) {
+ return new SimplePropertyObjectFactory<T>(property, value.getValue());
+ }
+ return new ObjectFactoryImpl<T>(property, value);
+ }
+
+ public class ObjectFactoryImpl<P> implements ObjectFactory<P> {
+ private Property<P> property;
+ private PropertyValue<P> propertyValue;
+ private DataType<QName> sourceDataType;
+ private DataType<?> targetDataType;
+
+ public ObjectFactoryImpl(Property<P> property, PropertyValue<P> propertyValue) {
+ this.property = property;
+ this.propertyValue = propertyValue;
+ sourceDataType = new DataType<QName>(DOMDataBinding.NAME, Node.class, this.property.getXmlType());
+ TypeInfo typeInfo = null;
+ if (this.property.getXmlType() != null) {
+ if (SimpleTypeMapperExtension.isSimpleXSDType(this.property.getXmlType())) {
+ typeInfo = new TypeInfo(property.getXmlType(), true, null);
+ } else {
+ typeInfo = new TypeInfo(property.getXmlType(), false, null);
+ }
+ } else {
+ typeInfo = new TypeInfo(property.getXmlType(), false, null);
+ }
+
+ ElementInfo elementInfo = new ElementInfo(null, typeInfo);
+ sourceDataType.setMetadata(ElementInfo.class.getName(), elementInfo);
+ Class javaType = this.property.getJavaType();
+ String dataBinding = (String) property.getExtensions().get(DataBinding.class.getName());
+ if (dataBinding != null) {
+ targetDataType = new DataType<Class>(dataBinding, javaType, javaType);
+ } else {
+ targetDataType = registry.introspectType(javaType);
+ if (targetDataType == null) {
+ targetDataType = new DataType<Class>("java.lang.Object", javaType, javaType);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public P getInstance() throws ObjectCreationException {
+ return (P) mediator.mediate(propertyValue.getValue(), sourceDataType, targetDataType, null);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java
new file mode 100644
index 0000000000..7e9c685bc7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.core.property;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.model.TypeInfo;
+import org.apache.tuscany.spi.model.Property;
+
+import org.w3c.dom.Document;
+
+public class SimplePropertyObjectFactory<P> implements ObjectFactory<P> {
+ private SimpleTypeMapperExtension typeMapper;
+ private Property<P> property;
+ private Document value;
+ private P instance;
+
+ public SimplePropertyObjectFactory(Property<P> property, Document value) {
+ super();
+
+ this.property = property;
+ this.value = (value == null) ? property.getDefaultValue() : value;
+ this.typeMapper = new SimpleTypeMapperExtension();
+ }
+
+ @SuppressWarnings("unchecked")
+ public P getInstance() throws ObjectCreationException {
+ if (value == null) {
+ return null;
+ }
+ if (instance == null) {
+ String text = value.getDocumentElement().getTextContent();
+ TypeInfo xmlType = null;
+ if (property.getJavaType() == null) {
+ xmlType = new TypeInfo(property.getXmlType(), true, null);
+ } else {
+ xmlType = typeMapper.getXMLType(property.getJavaType());
+ }
+ if (xmlType == null) {
+ throw new IllegalArgumentException("Complex property is not supported.");
+ }
+ instance = (P)typeMapper.toJavaObject(xmlType, text, null);
+ }
+ return instance;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireResolver.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireResolver.java
new file mode 100644
index 0000000000..06322f9c0f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireResolver.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.core.resolver;
+
+import java.net.URI;
+
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.resolver.ResolutionException;
+
+/**
+ * Implementations are responsible for resolving autowire targets in an SCA Domain. It is assumed that autowire
+ * resolution occurs after resource resolution as service interface classes may be laoded
+ *
+ * @version $Rev$ $Date$
+ */
+public interface AutowireResolver {
+
+ /**
+ * Resolves autowires for a component definition and its decendents
+ *
+ * @param parentDefinition the parent
+ * @param definition the component definition to resolve autowires for
+ * @throws ResolutionException
+ */
+ void resolve(ComponentDefinition<Implementation<CompositeComponentType<?, ?, ?>>> parentDefinition,
+ ComponentDefinition<? extends Implementation<?>> definition) throws ResolutionException;
+
+ /**
+ * Adds the uri of a host system service that can be an autowire target
+ *
+ * @param contract the service contract of the system service
+ * @param uri the component uri
+ */
+ void addHostUri(ServiceContract contract, URI uri);
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireTargetNotFoundException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireTargetNotFoundException.java
new file mode 100644
index 0000000000..1526724ca9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/AutowireTargetNotFoundException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.core.resolver;
+
+import org.apache.tuscany.spi.resolver.ResolutionException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AutowireTargetNotFoundException extends ResolutionException {
+ public AutowireTargetNotFoundException(String message, String identifier) {
+ super(message, identifier);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/DefaultAutowireResolver.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/DefaultAutowireResolver.java
new file mode 100644
index 0000000000..f83ec33241
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/resolver/DefaultAutowireResolver.java
@@ -0,0 +1,160 @@
+/*
+ * 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.core.resolver;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Implementation;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ReferenceTarget;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.apache.tuscany.spi.resolver.ResolutionException;
+
+/**
+ * Default implementation of an autowire resolver
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultAutowireResolver implements AutowireResolver {
+ private Map<ServiceContract, URI> hostAutowire = new HashMap<ServiceContract, URI>();
+
+
+ @SuppressWarnings({"unchecked"})
+ public void resolve(ComponentDefinition<Implementation<CompositeComponentType<?, ?, ?>>> parentDefinition,
+ ComponentDefinition<? extends Implementation<?>> definition)
+ throws ResolutionException {
+ ComponentType<?, ?, ?> type = definition.getImplementation().getComponentType();
+ // resolve autowires
+ if (type instanceof CompositeComponentType) {
+ CompositeComponentType<?, ?, ?> compositeType = (CompositeComponentType<?, ?, ?>) type;
+ for (ComponentDefinition<? extends Implementation<?>> child : compositeType.getComponents().values()) {
+ Implementation<?> implementation = child.getImplementation();
+ ComponentType<?, ?, ?> childType = implementation.getComponentType();
+ if (childType instanceof CompositeComponentType) {
+ // recurse decendents for composites
+ resolve((ComponentDefinition<Implementation<CompositeComponentType<?, ?, ?>>>) definition, child);
+ }
+ Map<String, ReferenceTarget> targets = child.getReferenceTargets();
+ for (ReferenceDefinition reference : childType.getReferences().values()) {
+ ReferenceTarget target = targets.get(reference.getUri().getFragment());
+ if (target == null) {
+ continue;
+ }
+ if (target.isAutowire()) {
+ ServiceContract requiredContract = reference.getServiceContract();
+ resolve(compositeType, requiredContract, target, reference.isRequired());
+ }
+ }
+ }
+ } else {
+ // a leaf level component
+ ComponentType<?, ?, ?> componentType = definition.getImplementation().getComponentType();
+ Map<String, ReferenceTarget> targets = definition.getReferenceTargets();
+ for (ReferenceDefinition reference : componentType.getReferences().values()) {
+ ReferenceTarget target = targets.get(reference.getUri().getFragment());
+ if (target == null) {
+ continue;
+ }
+ if (target.isAutowire()) {
+ ServiceContract requiredContract = reference.getServiceContract();
+ CompositeComponentType<?, ?, ?> ctype = parentDefinition.getImplementation().getComponentType();
+ resolve(ctype, requiredContract, target, reference.isRequired());
+ }
+ }
+ }
+ }
+
+ public void addHostUri(ServiceContract contract, URI uri) {
+ hostAutowire.put(contract, uri);
+ }
+
+ /**
+ * Performs the actual resolution against a composite TODO this should be extensible allowing for path
+ * optimizations
+ *
+ * @param compositeType the composite component type to resolve against
+ * @param requiredContract the required target contract
+ * @param target the reference target
+ * @param required true if the autowire is required
+ * @throws AutowireTargetNotFoundException
+ *
+ */
+ private void resolve(CompositeComponentType<?, ?, ?> compositeType,
+ ServiceContract requiredContract,
+ ReferenceTarget target,
+ boolean required) throws AutowireTargetNotFoundException {
+ // for now, attempt to match on interface, assume the class can be loaded
+ Class<?> requiredInterface = requiredContract.getInterfaceClass();
+ if (requiredInterface == null) {
+ throw new UnsupportedOperationException("Only interfaces support for autowire");
+ }
+ // autowire to a target in the parent
+ URI targetUri = null;
+ URI candidateUri = null;
+ // find a suitable target, starting with components first
+ for (ComponentDefinition<? extends Implementation<?>> candidate : compositeType.getComponents().values()) {
+ Implementation<?> candidateImpl = candidate.getImplementation();
+ ComponentType<?, ?, ?> candidateType = candidateImpl.getComponentType();
+ for (ServiceDefinition service : candidateType.getServices().values()) {
+ Class<?> serviceInterface = service.getServiceContract().getInterfaceClass();
+ if (serviceInterface == null) {
+ continue;
+ }
+ if (requiredInterface.equals(serviceInterface)) {
+ targetUri = URI.create(candidate.getUri().toString() + service.getUri());
+ break;
+ } else if (candidateUri == null && requiredInterface.isAssignableFrom(serviceInterface)) {
+ candidateUri = URI.create(candidate.getUri().toString() + service.getUri());
+ }
+ }
+ if (targetUri != null) {
+ break;
+ }
+ }
+ if (targetUri == null) {
+ targetUri = resolvePrimordial(requiredContract);
+ }
+ if (candidateUri != null) {
+ targetUri = candidateUri;
+ }
+ if (targetUri != null) {
+ target.addTarget(targetUri);
+ }
+ if (targetUri == null && required) {
+ String uri = target.getReferenceName().toString();
+ throw new AutowireTargetNotFoundException("No suitable target found for", uri);
+ }
+ }
+
+ private URI resolvePrimordial(ServiceContract contract) {
+ Class<?> requiredClass = contract.getInterfaceClass();
+ for (Map.Entry<ServiceContract, URI> entry : hostAutowire.entrySet()) {
+ if (requiredClass.isAssignableFrom(entry.getKey().getInterfaceClass())) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java
new file mode 100644
index 0000000000..e2d92711f6
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java
@@ -0,0 +1,301 @@
+/*
+ * 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.core.runtime;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.xml.stream.XMLInputFactory;
+
+import org.osoa.sca.ComponentContext;
+
+import org.apache.tuscany.spi.bootstrap.ComponentNames;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.ComponentException;
+import org.apache.tuscany.spi.component.RegistrationException;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.event.RuntimeEventListener;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.resolver.ResolutionException;
+import org.apache.tuscany.spi.services.management.TuscanyManagementService;
+
+import org.apache.tuscany.core.bootstrap.Bootstrapper;
+import org.apache.tuscany.core.bootstrap.DefaultBootstrapper;
+import org.apache.tuscany.core.builder.ConnectorImpl;
+import org.apache.tuscany.core.component.ComponentManager;
+import org.apache.tuscany.core.component.ComponentManagerImpl;
+import org.apache.tuscany.core.component.event.ComponentStart;
+import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl;
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+import org.apache.tuscany.core.monitor.NullMonitorFactory;
+import org.apache.tuscany.core.resolver.AutowireResolver;
+import org.apache.tuscany.core.resolver.DefaultAutowireResolver;
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.RuntimeInfo;
+import org.apache.tuscany.host.management.ManagementService;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+import org.apache.tuscany.host.runtime.InitializationException;
+import org.apache.tuscany.host.runtime.TuscanyRuntime;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractRuntime<I extends RuntimeInfo> implements TuscanyRuntime<I> {
+ private static final URI MONITOR_URI = ComponentNames.TUSCANY_SYSTEM_ROOT.resolve("MonitorFactory");
+
+ private static final URI COMPONENT_MGR_URI = ComponentNames.TUSCANY_SYSTEM_ROOT.resolve("ComponentManager");
+
+ private static final URI AUTOWIRE_RESOLVER_URI = ComponentNames.TUSCANY_SYSTEM_ROOT.resolve("AutowireResolver");
+
+ private static final URI RUNTIME_INFO_URI = ComponentNames.TUSCANY_SYSTEM_ROOT.resolve("RuntimeInfo");
+
+ private final XMLInputFactory xmlFactory;
+ private URL systemScdl;
+ private String applicationName;
+ private URL applicationScdl;
+ private ClassLoader hostClassLoader;
+ private ClassLoader applicationClassLoader;
+ private Class<I> runtimeInfoType;
+ private I runtimeInfo;
+ private MonitorFactory monitorFactory;
+ private ManagementService<?> managementService;
+ private ComponentManager componentManager;
+
+ private Component systemComponent;
+ private Component tuscanySystem;
+ private AutowireResolver resolver;
+ private JavaInterfaceProcessorRegistry interfaceProcessorRegistry;
+
+ protected AbstractRuntime(Class<I> runtimeInfoType) {
+ this(runtimeInfoType, new NullMonitorFactory());
+ }
+
+ protected AbstractRuntime(Class<I> runtimeInfoType, MonitorFactory monitorFactory) {
+ this.runtimeInfoType = runtimeInfoType;
+ this.monitorFactory = monitorFactory;
+ xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ this.interfaceProcessorRegistry = new JavaInterfaceProcessorRegistryImpl();
+ }
+
+ public URL getSystemScdl() {
+ return systemScdl;
+ }
+
+ public void setSystemScdl(URL systemScdl) {
+ this.systemScdl = systemScdl;
+ }
+
+ public String getApplicationName() {
+ return applicationName;
+ }
+
+ public void setApplicationName(String applicationName) {
+ this.applicationName = applicationName;
+ }
+
+ public URL getApplicationScdl() {
+ return applicationScdl;
+ }
+
+ public void setApplicationScdl(URL applicationScdl) {
+ this.applicationScdl = applicationScdl;
+ }
+
+ public ClassLoader getApplicationClassLoader() {
+ return applicationClassLoader;
+ }
+
+ public void setApplicationClassLoader(ClassLoader applicationClassLoader) {
+ this.applicationClassLoader = applicationClassLoader;
+ }
+
+ public ClassLoader getHostClassLoader() {
+ return hostClassLoader;
+ }
+
+ public void setHostClassLoader(ClassLoader hostClassLoader) {
+ this.hostClassLoader = hostClassLoader;
+ }
+
+ public I getRuntimeInfo() {
+ return runtimeInfo;
+ }
+
+ public void setRuntimeInfo(I runtimeInfo) {
+ this.runtimeInfo = runtimeInfo;
+ }
+
+ public MonitorFactory getMonitorFactory() {
+ return monitorFactory;
+ }
+
+ public void setMonitorFactory(MonitorFactory monitorFactory) {
+ this.monitorFactory = monitorFactory;
+ }
+
+ public ManagementService<?> getManagementService() {
+ return managementService;
+ }
+
+ public void setManagementService(ManagementService<?> managementService) {
+ this.managementService = managementService;
+ }
+
+ public void initialize() throws InitializationException {
+ URI name = ComponentNames.TUSCANY_SYSTEM_ROOT.resolve("main");
+ Bootstrapper bootstrapper = createBootstrapper();
+
+ registerBaselineSystemComponents();
+
+ // deploy the system scdl
+ Collection<Component> components;
+ try {
+ components = deploySystemScdl(bootstrapper.createDeployer(),
+ systemComponent,
+ name,
+ getSystemScdl(),
+ getClass().getClassLoader());
+ } catch (LoaderException e) {
+ throw new InitializationException(e);
+ } catch (BuilderException e) {
+ throw new InitializationException(e);
+ } catch (ComponentException e) {
+ throw new InitializationException(e);
+ } catch (ResolutionException e) {
+ throw new InitializationException(e);
+ }
+ for (Component component : components) {
+ component.start();
+ }
+ Component composite = componentManager.getComponent(name);
+ if (composite instanceof RuntimeEventListener) {
+ ((RuntimeEventListener) composite).onEvent(new ComponentStart(this, name));
+ }
+ }
+
+ public void destroy() {
+ if (tuscanySystem != null) {
+ tuscanySystem.stop();
+ tuscanySystem = null;
+ }
+ if (systemComponent != null) {
+ systemComponent.stop();
+ systemComponent = null;
+ }
+ }
+
+
+ public ComponentContext getComponentContext(URI componentId) {
+ Component component = componentManager.getComponent(componentId);
+ if (component == null) {
+ return null;
+ }
+ return component.getComponentContext();
+ }
+
+ protected Bootstrapper createBootstrapper() {
+ TuscanyManagementService tms = (TuscanyManagementService) getManagementService();
+ resolver = new DefaultAutowireResolver();
+ componentManager = new ComponentManagerImpl(tms, resolver);
+ Connector connector = new ConnectorImpl(componentManager);
+ return new DefaultBootstrapper(getMonitorFactory(), xmlFactory, componentManager, resolver, connector);
+ }
+
+ protected void registerBaselineSystemComponents() throws InitializationException {
+ registerSystemComponent(RUNTIME_INFO_URI, runtimeInfoType, runtimeInfo);
+ List<Class<?>> monitorServices = new ArrayList<Class<?>>();
+ monitorServices.add(MonitorFactory.class);
+ monitorServices.add(FormatterRegistry.class);
+ registerSystemComponent(MONITOR_URI, monitorServices, getMonitorFactory());
+ // register the component manager with itself so it can be autowired
+ registerSystemComponent(COMPONENT_MGR_URI, ComponentManager.class, componentManager);
+ registerSystemComponent(AUTOWIRE_RESOLVER_URI, AutowireResolver.class, resolver);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected <S, I extends S> void registerSystemComponent(URI uri, Class<S> type, I component)
+ throws InitializationException {
+ try {
+ ServiceContract contract = interfaceProcessorRegistry.introspect(type);
+ componentManager.registerJavaObject(uri, contract, component);
+ } catch (RegistrationException e) {
+ throw new InitializationException(e);
+ } catch (InvalidServiceContractException e) {
+ throw new InitializationException(e);
+ }
+ }
+
+ protected <I> void registerSystemComponent(URI uri, List<Class<?>> types, I component)
+ throws InitializationException {
+ try {
+ List<ServiceContract<?>> contracts = new ArrayList<ServiceContract<?>>();
+ for (Class<?> type : types) {
+ contracts.add(this.interfaceProcessorRegistry.introspect(type));
+
+ }
+ componentManager.registerJavaObject(uri, contracts, component);
+ } catch (RegistrationException e) {
+ throw new InitializationException(e);
+ } catch (InvalidServiceContractException e) {
+ throw new InitializationException(e);
+ }
+ }
+
+ protected Collection<Component> deploySystemScdl(Deployer deployer,
+ Component parent,
+ URI name,
+ URL systemScdl,
+ ClassLoader systemClassLoader)
+ throws LoaderException, BuilderException, ComponentException, ResolutionException {
+
+ SystemCompositeImplementation impl = new SystemCompositeImplementation();
+ impl.setScdlLocation(systemScdl);
+ impl.setClassLoader(systemClassLoader);
+ ComponentDefinition<SystemCompositeImplementation> definition =
+ new ComponentDefinition<SystemCompositeImplementation>(name, impl);
+
+ return deployer.deploy(parent, definition);
+ }
+
+
+ protected ComponentManager getComponentManager() {
+ return componentManager;
+ }
+
+
+ protected Deployer getDeployer() {
+ try {
+ AtomicComponent component =
+ (AtomicComponent) getComponentManager().getComponent(ComponentNames.TUSCANY_DEPLOYER);
+ return (Deployer) component.getTargetInstance();
+ } catch (TargetResolutionException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java
new file mode 100644
index 0000000000..f50e8544a3
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java
@@ -0,0 +1,100 @@
+/*
+ * 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.core.services.artifact;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+
+import org.osoa.sca.annotations.Property;
+
+import org.apache.tuscany.spi.services.artifact.Artifact;
+import org.apache.tuscany.spi.services.artifact.ArtifactRepository;
+
+/**
+ * An implementation of ArtifactRepository that uses a local Maven2 repository.
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalMavenRepository implements ArtifactRepository {
+ private File localRepo;
+
+ /**
+ * Constructor specifying the location of the local repo. Relative paths are resolved against the user's home
+ * directory.
+ *
+ * @param repoPath the path to the local repo
+ */
+ public LocalMavenRepository(@Property(name = "repository") String repoPath) {
+ String home = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty("user.home");
+ }
+ });
+ this.localRepo = new File(home, repoPath);
+ }
+
+ public void resolve(Artifact artifact) {
+ if (artifact.getUrl() != null) {
+ return;
+ }
+
+ String path = getPath(artifact);
+ File artifactFile = new File(localRepo, path);
+ if (artifactFile.exists()) {
+ try {
+ artifact.setUrl(artifactFile.toURI().toURL());
+ } catch (MalformedURLException e) {
+ // toURI should have escaped the filename to allow it to be converted to a URL
+ throw new AssertionError();
+ }
+ }
+ }
+
+ /**
+ * Return the path into the repo for an artifact. The path for an artifact is ${group.replace('.',
+ * '/')}/$[name}/${version}/${name}-${version}[-${classifier}].${type}
+ *
+ * @param artifact the artifact to resolve
+ * @return the path into the repo for the artifact
+ */
+ protected String getPath(Artifact artifact) {
+ StringBuilder builder = new StringBuilder();
+ if (artifact.getGroup() != null) {
+ builder.append(artifact.getGroup().replace('.', '/')).append('/');
+ }
+ builder.append(artifact.getName()).append('/');
+ builder.append(artifact.getVersion()).append('/');
+
+ builder.append(artifact.getName()).append('-').append(artifact.getVersion());
+ if (artifact.getClassifier() != null) {
+ builder.append('-').append(artifact.getClassifier());
+ }
+ builder.append('.').append(artifact.getType());
+ return builder.toString();
+ }
+
+ public void resolve(Collection<? extends Artifact> artifacts) {
+ for (Artifact artifact : artifacts) {
+ resolve(artifact);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/ClassLoaderRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/ClassLoaderRegistryImpl.java
new file mode 100644
index 0000000000..afa7f64246
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/ClassLoaderRegistryImpl.java
@@ -0,0 +1,50 @@
+/*
+ * 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.core.services.classloading;
+
+import java.net.URI;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.services.classloading.ClassLoaderRegistry;
+import org.apache.tuscany.spi.services.classloading.DuplicateClassLoaderException;
+
+/**
+ * Implementation of a registry for classloaders.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ClassLoaderRegistryImpl implements ClassLoaderRegistry {
+ private final Map<URI, ClassLoader> registry = new ConcurrentHashMap<URI, ClassLoader>();
+
+ public synchronized void register(URI id, ClassLoader classLoader) throws DuplicateClassLoaderException {
+ if (registry.containsKey(id)) {
+ throw new DuplicateClassLoaderException("Duplicate class loader", id.toString());
+ }
+ registry.put(id, classLoader);
+ }
+
+ public ClassLoader getClassLoader(URI id) {
+ return registry.get(id);
+ }
+
+ public ClassLoader unregister(URI id) {
+ return registry.remove(id);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/MultiParentClassLoader.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/MultiParentClassLoader.java
new file mode 100644
index 0000000000..0a255ede9e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/classloading/MultiParentClassLoader.java
@@ -0,0 +1,402 @@
+/*
+ * 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.core.services.classloading;
+
+import java.beans.Introspector;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.URLStreamHandlerFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A MultiParentClassLoader is a simple extension of the URLClassLoader that
+ * simply changes the single parent class loader model to support a list of
+ * parent class loaders. Each operation that accesses a parent, has been
+ * replaced with a operation that checks each parent in order. This getParent
+ * method of this class will always return null, which may be interpreted by the
+ * calling code to mean that this class loader is a direct child of the system
+ * class loader.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MultiParentClassLoader extends URLClassLoader {
+ private boolean destroyed;
+ private final String[] hiddenClasses;
+ private final String[] hiddenResources;
+ private final boolean inverseClassLoading;
+ private final String[] nonOverridableClasses;
+ private final String[] nonOverridableResources;
+
+ private final ClassLoader[] parents;
+
+ /**
+ * Creates a named class loader with no parents.
+ *
+ * @param urls the urls from which this class loader will classes and
+ * resources
+ */
+ public MultiParentClassLoader(URL[] urls) {
+ super(urls);
+ parents = new ClassLoader[] {ClassLoader.getSystemClassLoader()};
+ inverseClassLoading = false;
+ hiddenClasses = new String[0];
+ nonOverridableClasses = new String[0];
+ hiddenResources = new String[0];
+ nonOverridableResources = new String[0];
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified parent.
+ *
+ * @param urls the urls from which this class loader will classes and
+ * resources
+ * @param parent the parent of this class loader
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader parent) {
+ this(urls, new ClassLoader[] {parent});
+ }
+
+ public MultiParentClassLoader(URL[] urls,
+ ClassLoader parent,
+ boolean inverseClassLoading,
+ String[] hiddenClasses,
+ String[] nonOverridableClasses) {
+ this(urls, new ClassLoader[] {parent}, inverseClassLoading, hiddenClasses, nonOverridableClasses);
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified parent and using
+ * the specified URLStreamHandlerFactory for accessing the urls..
+ *
+ * @param urls the urls from which this class loader will classes and
+ * resources
+ * @param parent the parent of this class loader
+ * @param factory the URLStreamHandlerFactory used to access the urls
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
+ this(urls, new ClassLoader[] {parent}, factory);
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified parents.
+ *
+ * @param urls the urls from which this class loader will classes and
+ * resources
+ * @param parents the parents of this class loader
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader[] parents) {
+ super(urls);
+ this.parents = copyParents(parents);
+ inverseClassLoading = false;
+ hiddenClasses = new String[0];
+ nonOverridableClasses = new String[0];
+ hiddenResources = new String[0];
+ nonOverridableResources = new String[0];
+ }
+
+ public MultiParentClassLoader(URL[] urls,
+ ClassLoader[] parents,
+ boolean inverseClassLoading,
+ Collection<String> hiddenClasses,
+ Collection<String> nonOverridableClasses) {
+ this(urls, parents, inverseClassLoading, (String[])hiddenClasses.toArray(new String[hiddenClasses.size()]),
+ (String[])nonOverridableClasses.toArray(new String[nonOverridableClasses.size()]));
+ }
+
+ public MultiParentClassLoader(URL[] urls,
+ ClassLoader[] parents,
+ boolean inverseClassLoading,
+ String[] hiddenClasses,
+ String[] nonOverridableClasses) {
+ super(urls);
+ this.parents = copyParents(parents);
+ this.inverseClassLoading = inverseClassLoading;
+ this.hiddenClasses = hiddenClasses;
+ this.nonOverridableClasses = nonOverridableClasses;
+ hiddenResources = toResources(hiddenClasses);
+ nonOverridableResources = toResources(nonOverridableClasses);
+ }
+
+ /**
+ * Creates a named class loader as a child of the specified parents and
+ * using the specified URLStreamHandlerFactory for accessing the urls..
+ *
+ * @param urls the urls from which this class loader will classes and
+ * resources
+ * @param parents the parents of this class loader
+ * @param factory the URLStreamHandlerFactory used to access the urls
+ */
+ public MultiParentClassLoader(URL[] urls, ClassLoader[] parents, URLStreamHandlerFactory factory) {
+ super(urls, null, factory);
+ this.parents = copyParents(parents);
+ inverseClassLoading = false;
+ hiddenClasses = new String[0];
+ nonOverridableClasses = new String[0];
+ hiddenResources = new String[0];
+ nonOverridableResources = new String[0];
+ }
+
+ private static ClassLoader[] copyParents(ClassLoader[] parents) {
+ ClassLoader[] newParentsArray = new ClassLoader[parents.length];
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ if (parent == null) {
+ throw new RuntimeException("parent[" + i + "] is null");
+ }
+ newParentsArray[i] = parent;
+ }
+ return newParentsArray;
+ }
+
+ public void addURL(URL url) {
+ // todo this needs a security check
+ super.addURL(url);
+ }
+
+ public void destroy() {
+ synchronized (this) {
+ if (destroyed) {
+ return;
+ }
+ destroyed = true;
+ }
+
+ // clearSoftCache(ObjectInputStream.class, "subclassAudits");
+ // clearSoftCache(ObjectOutputStream.class, "subclassAudits");
+ // clearSoftCache(ObjectStreamClass.class, "localDescs");
+ // clearSoftCache(ObjectStreamClass.class, "reflectors");
+
+ // The beanInfoCache in java.beans.Introspector will hold on to Classes
+ // which
+ // it has introspected. If we don't flush the cache, we may run out of
+ // Permanent Generation space.
+ Introspector.flushCaches();
+ }
+
+ public Enumeration<URL> findResources(String name) throws IOException {
+ if (isDestroyed()) {
+ Set<URL> emptySet = Collections.emptySet();
+ return Collections.enumeration(emptySet);
+ }
+
+ List<URL> resources = new ArrayList<URL>();
+
+ //
+ // if we are using inverse class loading, add the resources from local
+ // urls first
+ //
+ if (inverseClassLoading && !isDestroyed()) {
+ List<URL> myResources = Collections.list(super.findResources(name));
+ resources.addAll(myResources);
+ }
+
+ //
+ // Add parent resources
+ //
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ List<URL> parentResources = Collections.list(parent.getResources(name));
+ resources.addAll(parentResources);
+ }
+
+ //
+ // if we are not using inverse class loading, add the resources from
+ // local urls now
+ //
+ if (!inverseClassLoading && !isDestroyed()) {
+ List<URL> myResources = Collections.list(super.findResources(name));
+ resources.addAll(myResources);
+ }
+
+ return Collections.enumeration(resources);
+ }
+
+ /**
+ * Gets the parents of this class loader.
+ *
+ * @return the parents of this class loader
+ */
+ public ClassLoader[] getParents() {
+ return parents;
+ }
+
+ public URL getResource(String name) {
+ if (isDestroyed()) {
+ return null;
+ }
+
+ //
+ // if we are using inverse class loading, check local urls first
+ //
+ if (inverseClassLoading && !isDestroyed() && !isNonOverridableResource(name)) {
+ URL url = findResource(name);
+ if (url != null) {
+ return url;
+ }
+ }
+
+ //
+ // Check parent class loaders
+ //
+ if (!isHiddenResource(name)) {
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ URL url = parent.getResource(name);
+ if (url != null) {
+ return url;
+ }
+ }
+ }
+
+ //
+ // if we are not using inverse class loading, check local urls now
+ //
+ // don't worry about excluding non-overridable resources here... we
+ // have alredy checked he parent and the parent didn't have the
+ // resource, so we can override now
+ if (!isDestroyed()) {
+ // parents didn't have the resource; attempt to load it from my urls
+ return findResource(name);
+ }
+
+ return null;
+ }
+
+ public synchronized boolean isDestroyed() {
+ return destroyed;
+ }
+
+ private boolean isHiddenClass(String name) {
+ for (int i = 0; i < hiddenClasses.length; i++) {
+ if (name.startsWith(hiddenClasses[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isHiddenResource(String name) {
+ for (int i = 0; i < hiddenResources.length; i++) {
+ if (name.startsWith(hiddenResources[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isNonOverridableClass(String name) {
+ for (int i = 0; i < nonOverridableClasses.length; i++) {
+ if (name.startsWith(nonOverridableClasses[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isNonOverridableResource(String name) {
+ for (int i = 0; i < nonOverridableResources.length; i++) {
+ if (name.startsWith(nonOverridableResources[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ //
+ // Check if class is in the loaded classes cache
+ //
+ Class cachedClass = findLoadedClass(name);
+ if (cachedClass != null) {
+ return resolveClass(cachedClass, resolve);
+ }
+
+ //
+ // if we are using inverse class loading, check local urls first
+ //
+ if (inverseClassLoading && !isDestroyed() && !isNonOverridableClass(name)) {
+ try {
+ Class clazz = findClass(name);
+ return resolveClass(clazz, resolve);
+ } catch (ClassNotFoundException ignored) {
+ // Ignore it
+ }
+ }
+
+ //
+ // Check parent class loaders
+ //
+ if (!isHiddenClass(name)) {
+ for (int i = 0; i < parents.length; i++) {
+ ClassLoader parent = parents[i];
+ try {
+ Class clazz = parent.loadClass(name);
+ return resolveClass(clazz, resolve);
+ } catch (ClassNotFoundException ignored) {
+ // this parent didn't have the class; try the next one
+ }
+ }
+ }
+
+ //
+ // if we are not using inverse class loading, check local urls now
+ //
+ // don't worry about excluding non-overridable classes here... we
+ // have alredy checked he parent and the parent didn't have the
+ // class, so we can override now
+ if (!isDestroyed()) {
+ try {
+ Class clazz = findClass(name);
+ return resolveClass(clazz, resolve);
+ } catch (ClassNotFoundException ignored) {
+ // Ignore it
+ }
+ }
+
+ throw new ClassNotFoundException(name);
+ }
+
+ private Class resolveClass(Class clazz, boolean resolve) {
+ if (resolve) {
+ resolveClass(clazz);
+ }
+ return clazz;
+ }
+
+ private String[] toResources(String[] classes) {
+ String[] resources = new String[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ String className = classes[i];
+ resources[i] = className.replace('.', '/');
+ }
+ return resources;
+ }
+
+ public String toString() {
+ return "[" + getClass().getName() + "]";
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java
new file mode 100644
index 0000000000..e264663dd4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.tuscany.host.deployment.AssemblyService;
+import org.apache.tuscany.host.deployment.DeploymentException;
+import org.apache.tuscany.host.deployment.UnsupportedContentTypeException;
+import org.apache.tuscany.spi.deployer.ChangeSetHandlerRegistry;
+import org.apache.tuscany.spi.deployer.ChangeSetHandler;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AssemblyServiceImpl implements AssemblyService, ChangeSetHandlerRegistry {
+ private final Map<String, ChangeSetHandler> registry = new HashMap<String, ChangeSetHandler>();
+
+ public void applyChanges(URL changeSet) throws DeploymentException, IOException {
+ if (changeSet == null) {
+ throw new IllegalArgumentException("changeSet is null");
+ }
+
+ URLConnection connection = changeSet.openConnection();
+ String contentType = connection.getContentType();
+ //todo try and figure out content type from the URL
+ if (contentType == null) {
+ throw new UnsupportedContentTypeException(null, changeSet.toString());
+ }
+
+ InputStream is = connection.getInputStream();
+ try {
+ applyChanges(is, contentType);
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ public void applyChanges(InputStream changeSet, String contentType) throws DeploymentException, IOException {
+ if (changeSet == null) {
+ throw new IllegalArgumentException("changeSet is null");
+ }
+ if (contentType == null) {
+ throw new IllegalArgumentException("contentType is null");
+ }
+
+ ChangeSetHandler handler = registry.get(contentType);
+ if (handler == null) {
+ throw new UnsupportedContentTypeException(contentType);
+ }
+
+ handler.applyChanges(changeSet);
+ }
+
+ public void register(ChangeSetHandler handler) {
+ registry.put(handler.getContentType(), handler);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java
new file mode 100644
index 0000000000..bae5c1d450
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java
@@ -0,0 +1,100 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.deployer.ContentTypeDescriber;
+
+import org.apache.tuscany.core.util.FileHelper;
+
+/**
+ * Implementation of the content describer
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+@Service(ContentTypeDescriber.class)
+public class ContentTypeDescriberImpl implements ContentTypeDescriber {
+ private final Map<String, String> contentTypeRegistry = new HashMap<String, String>();
+
+ public ContentTypeDescriberImpl() {
+ super();
+ init();
+ }
+
+ /**
+ * Initialize contentType registry with know types based on known file extensions
+ */
+ private void init() {
+ contentTypeRegistry.put("SCDL", "application/v.tuscany.scdl");
+ contentTypeRegistry.put("COMPOSITE", "application/v.tuscany.scdl");
+ contentTypeRegistry.put("WSDL", "application/v.tuscany.wsdl");
+ contentTypeRegistry.put("JAR", "application/x-compressed");
+ }
+
+ protected String resolveContentyTypeByExtension(URL resourceURL) {
+ String artifactExtension = FileHelper.getExtension(resourceURL.getPath());
+ if (artifactExtension == null) {
+ return null;
+ }
+ return contentTypeRegistry.get(artifactExtension.toUpperCase());
+ }
+
+ /**
+ * Build contentType for a specific resource. We first check if the file is a supported one (looking into our
+ * registry based on resource extension) If not found, we try to check file contentType Or we return
+ * defaultContentType provided
+ *
+ * @param url
+ * @param defaultContentType
+ * @return
+ */
+ public String getContentType(URL resourceURL, String defaultContentType) {
+ URLConnection connection = null;
+ String contentType = defaultContentType;
+
+ contentType = resolveContentyTypeByExtension(resourceURL);
+ if (contentType == null) {
+ try {
+ connection = resourceURL.openConnection();
+ contentType = connection.getContentType();
+
+ if (contentType == null || contentType.equals("content/unknown")) {
+ // here we couldn't figure out from our registry or from URL
+ // return defaultContentType if provided
+ contentType = defaultContentType;
+ }
+ } catch (IOException io) {
+ // could not access artifact, just ignore and we will return
+ // null contentType
+ }
+ }
+ return contentType == null ? defaultContentType : contentType;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java
new file mode 100644
index 0000000000..cbbd5f8623
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Init;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.host.deployment.ContributionService;
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+@EagerInit
+public class ContributionDirectoryWatcher {
+ private final String path;
+
+ private final ContributionService contributionService;
+
+ public ContributionDirectoryWatcher(@Reference ContributionService contributionService,
+ @Property(name = "path") String path) {
+ this.path = path;
+ this.contributionService = contributionService;
+ }
+
+ @Init
+ public void init() {
+ File extensionDir = new File(path);
+ if (!extensionDir.isDirectory()) {
+ // we don't have an extension directory, there's nothing to do
+ return;
+ }
+
+ File[] files = extensionDir.listFiles();
+ for (File file : files) {
+ try {
+ if (file.isDirectory()) {
+ this.contributionService.contribute(file.toURL(), false);
+ } else {
+ this.contributionService.contribute(file.toURL(), true);
+ }
+ } catch (DeploymentException de) {
+ // FIXME handle this
+ de.printStackTrace();
+ } catch (IOException ioe) {
+ // FIXME handle this
+ ioe.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java
new file mode 100644
index 0000000000..5866789e7e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java
@@ -0,0 +1,95 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.deployer.ContentTypeDescriber;
+import org.apache.tuscany.spi.deployer.ContributionProcessor;
+import org.apache.tuscany.spi.deployer.ContributionProcessorRegistry;
+import org.apache.tuscany.spi.model.Contribution;
+
+import org.apache.tuscany.host.deployment.DeploymentException;
+import org.apache.tuscany.host.deployment.UnsupportedContentTypeException;
+
+/**
+ * Default implementation of ContributionProcessorRegistry
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+@Service(ContributionProcessorRegistry.class)
+public class ContributionProcessorRegistryImpl implements ContributionProcessorRegistry {
+ /**
+ * Processor registry
+ */
+ private Map<String, ContributionProcessor> registry = new HashMap<String, ContributionProcessor>();
+ /**
+ * Helper method to describe contentType for each artifact
+ */
+ private ContentTypeDescriber contentTypeDescriber;
+
+ public ContributionProcessorRegistryImpl(@Reference ContentTypeDescriber contentTypeDescriber) {
+ if (contentTypeDescriber == null) {
+ this.contentTypeDescriber = new ContentTypeDescriberImpl();
+ } else {
+ this.contentTypeDescriber = contentTypeDescriber;
+ }
+ }
+
+ public void register(String contentType, ContributionProcessor processor) {
+ registry.put(contentType, processor);
+ }
+
+ public void unregister(String contentType) {
+ registry.remove(contentType);
+ }
+
+ public void processContent(Contribution contribution, URI source, InputStream inputStream)
+ throws DeploymentException, IOException {
+
+ URL locationURL = contribution.getArtifact(source).getLocation();
+ String contentType = this.contentTypeDescriber.getContentType(locationURL, null);
+ if (contentType == null) {
+ throw new UnsupportedContentTypeException("Invalid contentType: null");
+ }
+
+ ContributionProcessor processor = this.registry.get(contentType);
+ if (processor == null) {
+ throw new UnsupportedContentTypeException(contentType, locationURL.getPath());
+ }
+
+ processor.processContent(contribution, source, inputStream);
+
+ }
+
+ public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException,
+ IOException {
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java
new file mode 100644
index 0000000000..6f4509c23f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java
@@ -0,0 +1,144 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.core.util.FileHelper;
+import org.apache.tuscany.core.util.IOHelper;
+import org.apache.tuscany.spi.deployer.ContributionRepository;
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Init;
+import org.osoa.sca.annotations.Property;
+
+/**
+ * The default implementation of ContributionRepository
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class ContributionRepositoryImpl implements ContributionRepository {
+ protected final File rootFile;
+ protected final Map<URI, URL> reposirotyContent = new HashMap<URI, URL>();
+
+ /**
+ * Constructor with repository root
+ *
+ * @param repository
+ */
+ public ContributionRepositoryImpl(@Property(name = "repository") String repository) throws IOException {
+ this.rootFile = new File(repository);
+ FileHelper.forceMkdir(rootFile);
+ if (!rootFile.exists() || !rootFile.isDirectory() || !rootFile.canRead()) {
+ throw new IOException("The root is not a directory: " + repository);
+ }
+ }
+
+ /**
+ * Resolve contribution location in the repository -> root repository /
+ * contribution file -> contribution group id / artifact id / version
+ *
+ * @param contribution
+ * @return
+ */
+ private File mapToFile(URI contribution) {
+ // FIXME: Map the contribution URI to a file?
+ return new File(rootFile, FileHelper.getName(contribution.toString()));
+ }
+
+ /**
+ * Write a specific source inputstream to a file on disk
+ *
+ * @param source contents of the file to be written to disk
+ * @param target file to be written
+ * @throws IOException
+ */
+ public static void copy(InputStream source, File target) throws IOException {
+ BufferedOutputStream out = null;
+ BufferedInputStream in = null;
+
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(target));
+ in = new BufferedInputStream(source);
+ IOHelper.copy(in, out);
+ } finally {
+ IOHelper.closeQuietly(out);
+ IOHelper.closeQuietly(in);
+ }
+ }
+
+ public URL store(URI contribution, InputStream contributionStream) throws IOException {
+ // where the file should be stored in the repository
+ File location = mapToFile(contribution);
+
+ copy(contributionStream, location);
+
+ // add contribution to repositoryContent
+ URL contributionURL = location.toURL();
+ reposirotyContent.put(contribution, contributionURL);
+
+ return contributionURL;
+ }
+
+ public URL find(URI contribution) {
+ if (contribution == null) {
+ return null;
+ }
+ return this.reposirotyContent.get(contribution);
+ }
+
+ public void remove(URI contribution) {
+ URL contributionURL = this.find(contribution);
+ if (contributionURL != null) {
+ // remove
+ try {
+ FileHelper.forceDelete(FileHelper.toFile(contributionURL));
+ this.reposirotyContent.remove(contribution);
+ } catch (IOException ioe) {
+ // handle file could not be removed
+ }
+ }
+ }
+
+ public List<URI> list() {
+ return new ArrayList<URI>(reposirotyContent.keySet());
+ }
+
+ @Init
+ public void init() {
+ }
+
+ @Destroy
+ public void destroy() {
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java
new file mode 100644
index 0000000000..bf19683a7c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java
@@ -0,0 +1,137 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.ContributionProcessorRegistry;
+import org.apache.tuscany.spi.deployer.ContributionRepository;
+import org.apache.tuscany.spi.model.Contribution;
+
+import org.apache.tuscany.core.util.IOHelper;
+import org.apache.tuscany.host.deployment.ContributionService;
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ContributionServiceImpl implements ContributionService {
+ /**
+ * Repository where contributions are stored. Usually set by injection.
+ */
+ protected ContributionRepository contributionRepository;
+ /**
+ * Registry of available processors. Usually set by injection.
+ */
+ protected ContributionProcessorRegistry processorRegistry;
+ /**
+ * Contribution registry This is a registry of processed Contributios index by URI
+ */
+ protected Map<URI, Contribution> contributionRegistry = new HashMap<URI, Contribution>();
+
+ public ContributionServiceImpl(@Reference ContributionRepository repository,
+ @Reference ContributionProcessorRegistry processorRegistry) {
+ super();
+ this.contributionRepository = repository;
+ this.processorRegistry = processorRegistry;
+ }
+
+ public URI contribute(URL contribution, boolean storeInRepository) throws DeploymentException, IOException {
+ if (contribution == null) {
+ throw new IllegalArgumentException("contribution is null");
+ }
+
+ URI source;
+ try {
+ source = contribution.toURI();
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("contribution cannot be converted to a URI", e);
+ }
+
+ InputStream is = contribution.openConnection().getInputStream();
+ try {
+ return contribute(source, is, storeInRepository);
+ } finally {
+ IOHelper.closeQuietly(is);
+ }
+ }
+
+ public URI contribute(URI source, InputStream contributionStream, boolean storeInRepository)
+ throws DeploymentException, IOException {
+ if (source == null) {
+ throw new IllegalArgumentException("source URI for contribution is null");
+ }
+
+ if (contributionStream == null) {
+ throw new IllegalArgumentException("Invalid contribution stream : null");
+ }
+
+ // store the contribution in the contribution repository
+ URI contributionURI = URI.create("sca://contribution/" + UUID.randomUUID());
+ URL locationURL;
+ if (storeInRepository) {
+ locationURL = this.contributionRepository.store(source, contributionStream);
+ } else {
+ locationURL = source.toURL();
+ }
+
+
+ Contribution contribution = null;
+ contribution = new Contribution(contributionURI);
+ contribution.setLocation(locationURL);
+
+ //process the contribution
+ this.processorRegistry.processContent(contribution, contributionURI, locationURL.openStream());
+
+ //store the contribution on the registry
+ this.contributionRegistry.put(contribution.getUri(), contribution);
+
+ return contribution.getUri();
+ }
+
+ public Contribution getContribution(URI id) {
+ return this.contributionRegistry.get(id);
+ }
+
+ public void remove(URI contribution) throws DeploymentException {
+ //remove from repository
+ this.contributionRegistry.remove(contribution);
+ //remove from registry
+ this.contributionRegistry.remove(contribution);
+ }
+
+ public <T> T resolve(URI contribution, Class<T> definitionType, String namespace, String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public URL resolve(URI contribution, String namespace, URI uri, URI baseURI) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java
new file mode 100644
index 0000000000..f509929f29
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.services.deployment;
+
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+/**
+ * Exception that indicates that the supplied XML Document invalid.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidDocumentException extends DeploymentException {
+ protected InvalidDocumentException(String rootElement) {
+ super(rootElement);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java
new file mode 100644
index 0000000000..b3b38cb438
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java
@@ -0,0 +1,116 @@
+/*
+ * 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.core.services.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.builder.Builder;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.deployer.ChangeSetHandler;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.loader.Loader;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+
+import org.apache.tuscany.core.deployer.RootDeploymentContext;
+import org.apache.tuscany.host.deployment.ContentTypes;
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class XMLChangeSetHandler implements ChangeSetHandler {
+ private static final String NS = "http://tuscany.apache.org/xmlns/1.0-SNAPSHOT";
+ private static final QName CHANGESET = new QName(NS, "changeSet");
+ private static final QName CREATECOMPONENT = new QName(NS, "createComponent");
+
+ private final Builder builder;
+ private final Loader loader;
+ private final XMLInputFactory xmlFactory;
+
+ public XMLChangeSetHandler(Loader loader, Builder builder) {
+ this.loader = loader;
+ this.builder = builder;
+ xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ }
+
+ public String getContentType() {
+ return ContentTypes.CHANGESET_XML;
+ }
+
+ public void applyChanges(InputStream changeSet) throws DeploymentException, IOException {
+ try {
+ XMLStreamReader xmlReader = xmlFactory.createXMLStreamReader(changeSet);
+ while (true) {
+ switch (xmlReader.next()) {
+ case START_ELEMENT:
+ if (!CHANGESET.equals(xmlReader.getName())) {
+ throw new InvalidDocumentException(xmlReader.getName().toString());
+ }
+ processChanges(xmlReader);
+ break;
+ case END_DOCUMENT:
+ return;
+ }
+ }
+ } catch (XMLStreamException e) {
+ throw (IOException) new IOException(e.getMessage()).initCause(e);
+ }
+ }
+
+ public void processChanges(XMLStreamReader xmlReader) throws XMLStreamException, DeploymentException {
+ while (true) {
+ switch (xmlReader.next()) {
+ case START_ELEMENT:
+ if (CREATECOMPONENT.equals(xmlReader.getName())) {
+ createComponent(xmlReader);
+ } else {
+ // reject unrecognized commands
+ throw new InvalidDocumentException(xmlReader.getName().toString());
+ }
+ break;
+ case END_ELEMENT:
+ return;
+ }
+ }
+ }
+
+ public void createComponent(XMLStreamReader xmlReader) throws XMLStreamException {
+ DeploymentContext deploymentContext = new RootDeploymentContext(null, null, null, xmlFactory, null, false);
+ try {
+ ComponentDefinition<?> componentDefinition =
+ (ComponentDefinition<?>) loader.load(null, xmlReader, deploymentContext);
+ builder.build(componentDefinition, deploymentContext);
+ } catch (LoaderException e) {
+ // FIXME throw something appropriate
+ throw new AssertionError("FIXME");
+ } catch (BuilderException e) {
+ // FIXME throw something appropriate
+ throw new AssertionError("FIXME");
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java
new file mode 100644
index 0000000000..0855bb9d9a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java
@@ -0,0 +1,125 @@
+/*
+ * 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.core.services.deployment.contribution;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.core.services.deployment.ContentTypeDescriberImpl;
+import org.apache.tuscany.host.deployment.DeploymentException;
+import org.apache.tuscany.spi.deployer.ContentTypeDescriber;
+import org.apache.tuscany.spi.deployer.ContributionProcessor;
+import org.apache.tuscany.spi.extension.ContributionProcessorExtension;
+import org.apache.tuscany.spi.model.Contribution;
+
+public class FolderContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor {
+ public static final String CONTENT_TYPE = "application/v.tuscany.folder";
+
+ @Override
+ public String getContentType() {
+ return CONTENT_TYPE;
+ }
+
+
+ private void traverse(List<URL> fileList, File root) throws IOException {
+ if (root.isFile()) {
+ fileList.add(root.toURL());
+ } else if (root.isDirectory() && !root.getName().equals(".svn")) {
+ File[] files = root.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ traverse(fileList, files[i]);
+ }
+ }
+ }
+
+
+ /**
+ * Get a list of files from the directory
+ *
+ * @return
+ * @throws IOException
+ */
+ protected List<URL> getArtifacts(URL rootURL, InputStream sourceInputStream)
+ throws DeploymentException, IOException {
+ List<URL> artifacts = new ArrayList<URL>();
+
+ // Assume the root is a jar file
+ File rootFolder;
+
+ try {
+ rootFolder = new File(rootURL.toURI());
+ if (rootFolder.isDirectory()) {
+ this.traverse(artifacts, rootFolder);
+ }
+
+ } catch (URISyntaxException e) {
+ throw new InvalidFolderContributionURIException(rootURL.toExternalForm(), e);
+ }
+
+ return artifacts;
+ }
+
+
+ public void processContent(Contribution contribution, URI source, InputStream inputStream)
+ throws DeploymentException, IOException {
+ if (contribution == null) {
+ throw new IllegalArgumentException("Invalid null contribution.");
+ }
+
+ if (source == null) {
+ throw new IllegalArgumentException("Invalid null source uri.");
+ }
+
+ URL sourceURL = contribution.getArtifact(source).getLocation();
+
+ for (URL artifactURL : getArtifacts(sourceURL, inputStream)) {
+ // FIXME
+ // contribution.addArtifact(artifact)
+
+ ContentTypeDescriber contentTypeDescriber = new ContentTypeDescriberImpl();
+ String contentType = contentTypeDescriber.getContentType(artifactURL, null);
+ System.out.println("File : " + artifactURL);
+ System.out.println("Type : " + contentType);
+
+
+ //just process scdl for now
+ if ("application/v.tuscany.scdl".equals(contentType) || "application/java-vm".equals(contentType)) {
+ this.registry.processContent(contribution, source, inputStream);
+ }
+ // process each artifact
+ //this.registry.processContent(contribution, artifactURL, inputStream);
+
+ }
+
+ }
+
+ public void processModel(Contribution contribution, URI source, Object modelObject)
+ throws DeploymentException, IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java
new file mode 100644
index 0000000000..f0b47ccf7b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java
@@ -0,0 +1,36 @@
+/*
+ * 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.core.services.deployment.contribution;
+
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+/**
+ * Exception that indicates that the supplied XML Document invalid.
+ *
+ */
+public class InvalidComponentDefinitionlException extends DeploymentException {
+
+ protected InvalidComponentDefinitionlException(String componentDefinitionLocatoin) {
+ super(componentDefinitionLocatoin);
+ }
+
+ protected InvalidComponentDefinitionlException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java
new file mode 100644
index 0000000000..547608e64d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.services.deployment.contribution;
+
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+/**
+ * Exception that indicates that the supplied XML Document invalid.
+ *
+ */
+public class InvalidFolderContributionURIException extends DeploymentException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1564255850052593282L;
+
+ protected InvalidFolderContributionURIException(String componentDefinitionLocatoin) {
+ super(componentDefinitionLocatoin);
+ }
+
+ protected InvalidFolderContributionURIException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java
new file mode 100644
index 0000000000..6c9674f6fb
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java
@@ -0,0 +1,144 @@
+/*
+ * 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.core.services.deployment.contribution;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import org.apache.tuscany.core.services.deployment.ContentTypeDescriberImpl;
+import org.apache.tuscany.core.util.FileHelper;
+import org.apache.tuscany.host.deployment.DeploymentException;
+import org.apache.tuscany.spi.deployer.ContentTypeDescriber;
+import org.apache.tuscany.spi.deployer.ContributionProcessor;
+import org.apache.tuscany.spi.extension.ContributionProcessorExtension;
+import org.apache.tuscany.spi.model.Contribution;
+import org.apache.tuscany.spi.model.DeployedArtifact;
+
+public class JarContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor {
+ public static final String CONTENT_TYPE = "application/x-compressed";
+
+ @Override
+ public String getContentType() {
+ return CONTENT_TYPE;
+ }
+
+ /**
+ * Get a list of resources inside the jar
+ *
+ * @return
+ * @throws IOException
+ */
+ protected List<URL> getArtifacts(URL rootURL, InputStream sourceInputStream) throws IOException {
+ List<URL> artifacts = new ArrayList<URL>();
+
+ // Assume the root is a jar file
+ JarInputStream jar = new JarInputStream(sourceInputStream);
+ try {
+ while (true) {
+ JarEntry entry = jar.getNextJarEntry();
+ if (entry == null) {
+ // EOF
+ break;
+ }
+ if (entry.isDirectory()) {
+ continue;
+ }
+
+ artifacts.add(new URL(rootURL, entry.getName()));
+ }
+ } finally {
+ jar.close();
+ }
+ return artifacts;
+ }
+
+ private URL forceJarURL(URL sourceURL) throws MalformedURLException {
+ if (sourceURL.toString().startsWith("jar:")) {
+ return sourceURL;
+ } else {
+ return new URL("jar:" + sourceURL.toExternalForm() + "!/");
+ }
+
+ }
+
+ public void processContent(Contribution contribution, URI source, InputStream inputStream)
+ throws DeploymentException, IOException {
+ if (contribution == null) {
+ throw new IllegalArgumentException("Invalid null contribution.");
+ }
+
+ if (source == null) {
+ throw new IllegalArgumentException("Invalid null source uri.");
+ }
+
+ if (inputStream == null) {
+ throw new IllegalArgumentException("Invalid null source inputstream.");
+ }
+
+ URL sourceURL = contribution.getArtifact(source).getLocation();
+
+ sourceURL = forceJarURL(sourceURL);
+
+ for (URL artifactURL : getArtifacts(sourceURL, inputStream)) {
+ URI artifactURI;
+
+ try {
+ artifactURI = new URI(source.toASCIIString() + "/" + FileHelper.getName(artifactURL.getPath()));
+ DeployedArtifact artifact = new DeployedArtifact(artifactURI);
+ artifact.setLocation(artifactURL);
+ contribution.addArtifact(artifact);
+
+
+ ContentTypeDescriber contentTypeDescriber = new ContentTypeDescriberImpl();
+ String contentType = contentTypeDescriber.getContentType(artifactURL, null);
+ System.out.println("Type : " + contentType);
+
+
+ //just process scdl for now
+ if ("application/v.tuscany.scdl".equals(contentType)
+ /* || "application/java-vm".equals(contentType) */) {
+ this.registry.processContent(contribution, artifactURI, artifactURL.openStream());
+ }
+ } catch (URISyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+
+ }
+
+ }
+
+ public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException,
+ IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java
new file mode 100644
index 0000000000..d167ec42de
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java
@@ -0,0 +1,101 @@
+/*
+ * 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.core.services.deployment.contribution;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.CompositeClassLoader;
+import org.apache.tuscany.spi.deployer.ContributionProcessor;
+import org.apache.tuscany.spi.extension.ContributionProcessorExtension;
+import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry;
+import org.apache.tuscany.spi.model.Contribution;
+
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+public class JavaContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor {
+ public static final String CONTENT_TYPE = "application/java-vm";
+ //private Introspector introspector;
+
+ @Constructor
+ public JavaContributionProcessor(@Reference IntrospectionRegistry introspector) {
+ //this.introspector = introspector;
+ }
+
+ @Override
+ public String getContentType() {
+ return CONTENT_TYPE;
+ }
+
+ private String getClazzName(URL clazzURL) {
+ String clazzName;
+
+ clazzName = clazzURL.toExternalForm().substring(clazzURL.toExternalForm().lastIndexOf("!/") + 2,
+ clazzURL.toExternalForm().length() - ".class".length());
+ clazzName = clazzName.replace("/", ".");
+
+ return clazzName;
+ }
+
+
+ public void processContent(Contribution contribution, URI source, InputStream inputStream)
+ throws DeploymentException, IOException {
+ if (source == null) {
+ throw new IllegalArgumentException("Invalid null source uri.");
+ }
+
+ if (inputStream == null) {
+ throw new IllegalArgumentException("Invalid null source inputstream.");
+ }
+
+ // TODO Auto-generated method stub
+
+ //try {
+ CompositeClassLoader cl = new CompositeClassLoader(getClass().getClassLoader());
+ cl.addURL(contribution.getLocation());
+
+ String clazzName = getClazzName(contribution.getArtifact(source).getLocation());
+ System.out.println(clazzName);
+
+ //Class clazz = cl.loadClass(clazzName);
+
+// PojoComponentType javaInfo = introspector.introspect(null, clazz, null, null);
+// } catch (ClassNotFoundException cnfe) {
+// String msg = cnfe.getMessage();
+//
+// }
+// catch(ProcessingException pe){
+// String msg = pe.getMessage();
+
+
+ }
+
+ public void processModel(Contribution contribution, URI source, Object modelObject)
+ throws DeploymentException, IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/ScdlContributionProcessor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/ScdlContributionProcessor.java
new file mode 100644
index 0000000000..1be4f3e2d4
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/ScdlContributionProcessor.java
@@ -0,0 +1,105 @@
+/*
+ * 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.core.services.deployment.contribution;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import javax.xml.stream.XMLInputFactory;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.deployer.CompositeClassLoader;
+import org.apache.tuscany.spi.deployer.ContributionProcessor;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ContributionProcessorExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.CompositeImplementation;
+import org.apache.tuscany.spi.model.Contribution;
+
+import org.apache.tuscany.core.deployer.RootDeploymentContext;
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+public class ScdlContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor {
+ public static final String CONTENT_TYPE = "application/v.tuscany.scdl";
+
+ private final LoaderRegistry registry;
+
+ private final XMLInputFactory xmlFactory;
+
+ public ScdlContributionProcessor(@Reference LoaderRegistry registry) {
+ super();
+ this.registry = registry;
+ this.xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ }
+
+ @Override
+ public String getContentType() {
+ return CONTENT_TYPE;
+ }
+
+
+ public void processContent(Contribution contribution, URI source, InputStream inputStream)
+ throws DeploymentException, IOException {
+ if (source == null) {
+ throw new IllegalArgumentException("Invalid null source uri.");
+ }
+
+ if (inputStream == null) {
+ throw new IllegalArgumentException("Invalid null source inputstream.");
+ }
+
+ try {
+ URI contributionId = contribution.getUri();
+ URL scdlLocation = contribution.getArtifact(source).getLocation();
+ CompositeClassLoader cl = new CompositeClassLoader(getClass().getClassLoader());
+ cl.addURL(contribution.getLocation());
+
+ DeploymentContext deploymentContext =
+ new RootDeploymentContext(cl, scdlLocation, contributionId, this.xmlFactory, null,
+ false);
+
+ CompositeComponentType componentType =
+ this.registry.load(null, scdlLocation, CompositeComponentType.class, deploymentContext);
+
+ CompositeImplementation implementation = new CompositeImplementation();
+ implementation.setComponentType(componentType);
+ ComponentDefinition<CompositeImplementation> componentDefinition =
+ new ComponentDefinition<CompositeImplementation>(implementation);
+
+ contribution.getArtifact(source).addModelObject(null, null, componentDefinition);
+
+ } catch (LoaderException le) {
+ throw new InvalidComponentDefinitionlException(contribution.getArtifact(source).getLocation()
+ .toExternalForm(), le);
+ }
+ }
+
+ public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException,
+ IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+} \ No newline at end of file
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java
new file mode 100644
index 0000000000..37e599cc7b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.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.core.services.extension;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.deployer.Deployer;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AbstractExtensionDeployer {
+ protected Deployer deployer;
+ protected Component parent;
+
+ @Reference
+ public void setDeployer(Deployer deployer) {
+ this.deployer = deployer;
+ }
+
+ protected void deployExtension(File file) {
+ // extension name is file name less any extension
+ String name = file.getName();
+ int dot = name.lastIndexOf('.');
+ if (dot > 0) {
+ name = name.substring(0, dot);
+ }
+ URL url;
+ try {
+ url = file.toURI().toURL();
+ } catch (MalformedURLException e) {
+ // toURI should have encoded the URL
+ throw new AssertionError();
+ }
+
+ deployExtension(name, url);
+ }
+
+ protected void deployExtension(String name, URL url) {
+ throw new UnsupportedOperationException("");
+// // FIXME for now, assume this class's ClassLoader is the Tuscany system classloader
+// // FIXME we should really use the one associated with the parent composite
+// CompositeClassLoader extensionCL = new CompositeClassLoader(getClass().getClassLoader());
+//
+// // see if the URL points to a composite JAR by looking for a default SCDL file inside it
+// URL scdlLocation;
+// try {
+// scdlLocation = new URL("jar:" + url.toExternalForm() + "!/META-INF/sca/default.scdl");
+// } catch (MalformedURLException e) {
+// // the form of the jar: URL should be correct given url.toExternalForm() worked
+// throw new AssertionError();
+// }
+// try {
+// scdlLocation.openStream().close();
+// // we connected to the SCDL so let's add the JAR file to the classloader
+// extensionCL.addURL(url);
+// } catch (IOException e) {
+// // assume that the URL we were given is not a JAR file so just use the supplied resource
+// scdlLocation = url;
+// }
+//
+// // create a ComponentDefinition to represent the component we are going to deploy
+// SystemCompositeImplementation implementation = new SystemCompositeImplementation();
+// implementation.setScdlLocation(scdlLocation);
+// implementation.setClassLoader(extensionCL);
+// URI uri = parent.getUri().resolve(name);
+// ComponentDefinition<SystemCompositeImplementation> definition =
+// new ComponentDefinition<SystemCompositeImplementation>(uri, implementation);
+//
+// // FIXME: [rfeng] Should we reset the thread context class loader here?
+// // From the debugger with tomcat, the current TCCL is the RealmClassLoader
+// // ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
+// try {
+// // Thread.currentThread().setContextClassLoader(extensionCL);
+// Component component;
+// try {
+// component = deployer.deploy(parent, definition);
+// component.start();
+// } catch (BuilderException e) {
+// // FIXME JFM handle the exception
+// e.printStackTrace();
+// } catch (ComponentException e) {
+// // FIXME handle the exception
+// e.printStackTrace();
+// } catch (ResolutionException e) {
+// // FIXME handle the exception
+// e.printStackTrace();
+// }
+// } catch (LoaderException e) {
+// // FIXME handle the exception
+// e.printStackTrace();
+// }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java
new file mode 100644
index 0000000000..38ce4d16d2
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java
@@ -0,0 +1,142 @@
+/*
+ * 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.core.services.host;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.host.ResourceHost;
+import org.apache.tuscany.spi.host.ResourceHostRegistry;
+import org.apache.tuscany.spi.host.ResourceResolutionException;
+
+/**
+ * The default implementation of a <code>ResourceRegisty</code> that resolves resources in the <code>SCA://</code>
+ * namespace against its parent composite and delegates resolution to registered <code>ResourceHost</code>s for other
+ * namespaces. The search order for resources resolved by type starts with the SCA namespace and proceeds to hosts in
+ * the order they were registered.
+ *
+ * @version $Rev$ $Date$
+ */
+@Service(interfaces = {ResourceHost.class, ResourceHostRegistry.class})
+public class DelegatingResourceHostRegistry implements ResourceHost, ResourceHostRegistry {
+ private static final String SCA_PREFIX = "SCA://";
+ private Map<String, ResourceHost> resourceHosts = new HashMap<String, ResourceHost>();
+ private Map<Class<?>, Object> systemResources = new HashMap<Class<?>, Object>();
+ private Map<Key, Object> mappedSystemResources = new HashMap<Key, Object>();
+
+ public DelegatingResourceHostRegistry() {
+ }
+
+ public void registerResourceHost(String uri, ResourceHost host) {
+ resourceHosts.put(uri, host);
+ }
+
+ public void unregisterResourceHost(String uri) {
+ resourceHosts.remove(uri);
+ }
+
+ public void registerResource(Class<?> type, Object resource) {
+ systemResources.put(type, resource);
+ }
+
+ public void registerResource(Class<?> type, String name, Object resource) {
+ mappedSystemResources.put(new Key(type, name), resource);
+ }
+
+ public void unregisterResource(Class<?> type, String name) {
+ mappedSystemResources.remove(new Key(type, name));
+ }
+
+ public void unregisterResource(Class<?> type) {
+ systemResources.remove(type);
+ }
+
+ public <T> T resolveResource(Class<T> type) throws ResourceResolutionException {
+ T instance = type.cast(systemResources.get(type));
+ if (instance == null) {
+ for (ResourceHost host : resourceHosts.values()) {
+ instance = host.resolveResource(type);
+ if (instance != null) {
+ return instance;
+ }
+ }
+ }
+ return instance;
+ }
+
+ public <T> T resolveResource(Class<T> type, String mappedName) throws ResourceResolutionException {
+ if (mappedName.startsWith(SCA_PREFIX)) {
+ String name = mappedName.substring(SCA_PREFIX.length());
+ return type.cast(mappedSystemResources.get(new Key(type, name)));
+ } else {
+ int pos = mappedName.indexOf("://");
+ if (pos == -1) {
+ return type.cast(mappedSystemResources.get(new Key(type, mappedName)));
+ }
+ String uri = mappedName.substring(0, pos + 3);
+ ResourceHost host = resourceHosts.get(uri);
+ if (host == null) {
+ throw new ResourceResolutionException("No resource host for URI", uri);
+ }
+ return host.resolveResource(type, mappedName);
+ }
+ }
+
+ private class Key {
+ private Class<?> clazz;
+ private String name;
+
+ public Key(Class<?> clazz, String name) {
+ this.clazz = clazz;
+ this.name = name;
+ }
+
+ public Key(Class<?> clazz) {
+ this.clazz = clazz;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Key key = (Key) o;
+
+ if (clazz != null ? !clazz.equals(key.clazz) : key.clazz != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(key.name) : key.name != null) {
+ return false;
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = clazz != null ? clazz.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java
new file mode 100644
index 0000000000..a48cd5a2d7
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java
@@ -0,0 +1,198 @@
+/*
+ * 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.core.services.store.memory;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Init;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.event.AbstractEventPublisher;
+import org.apache.tuscany.spi.services.store.DuplicateRecordException;
+import org.apache.tuscany.spi.services.store.RecoveryListener;
+import org.apache.tuscany.spi.services.store.Store;
+import org.apache.tuscany.spi.services.store.StoreExpirationEvent;
+import org.apache.tuscany.spi.services.store.StoreMonitor;
+import org.apache.tuscany.spi.services.store.StoreWriteException;
+
+import org.apache.tuscany.api.annotation.Monitor;
+
+/**
+ * Implements a non-durable, non-transactional store using a simple in-memory map
+ *
+ * @version $Rev$ $Date$
+ */
+@Service(Store.class)
+@EagerInit
+public class MemoryStore extends AbstractEventPublisher implements Store {
+ private Map<SCAObject, Map<String, Record>> store;
+ // TODO integrate with a core threading scheme
+ private ScheduledExecutorService scheduler;
+ private long reaperInterval = 300000;
+ private StoreMonitor monitor;
+ private long defaultExpirationOffset = 600000; // 10 minutes
+
+ public MemoryStore(@Monitor StoreMonitor monitor) {
+ this.monitor = monitor;
+ this.store = new ConcurrentHashMap<SCAObject, Map<String, Record>>();
+ this.scheduler = Executors.newSingleThreadScheduledExecutor();
+ }
+
+ /**
+ * Returns the maximum default expiration offset for records in the store
+ *
+ * @return the maximum default expiration offset for records in the store
+ */
+ public long getDefaultExpirationOffset() {
+ return defaultExpirationOffset;
+ }
+
+ /**
+ * Sets the maximum default expiration offset for records in the store
+ */
+ @Property
+ public void setDefaultExpirationOffset(long defaultExpirationOffset) {
+ this.defaultExpirationOffset = defaultExpirationOffset;
+ }
+
+ /**
+ * Sets the interval for expired entry scanning to be performed
+ */
+ @Property
+ public void setReaperInterval(long reaperInterval) {
+ this.reaperInterval = reaperInterval;
+ }
+
+ public long getReaperInterval() {
+ return reaperInterval;
+ }
+
+ @Init
+ public void init() {
+ scheduler.scheduleWithFixedDelay(new Reaper(), reaperInterval, reaperInterval, TimeUnit.MILLISECONDS);
+ monitor.start("In-memory store started");
+ }
+
+ @Destroy
+ public void destroy() {
+ scheduler.shutdown();
+ monitor.stop("In-memory store stopped");
+ }
+
+ public void insertRecord(SCAObject owner, String id, Object object, long expiration) throws StoreWriteException {
+ Map<String, Record> map = store.get(owner);
+ if (map == null) {
+ map = new ConcurrentHashMap<String, Record>();
+ store.put(owner, map);
+ }
+ if (map.containsKey(id)) {
+ throw new DuplicateRecordException(owner.getUri().toString(), id);
+ }
+ map.put(id, new Record(object, expiration));
+ }
+
+ public void updateRecord(SCAObject owner, String id, Object object, long expiration) throws StoreWriteException {
+ Map<String, Record> map = store.get(owner);
+ if (map == null) {
+ throw new StoreWriteException("Record not found", owner.getUri().toString(), id);
+ }
+ Record record = map.get(id);
+ if (record == null) {
+ throw new StoreWriteException("Record not found", owner.getUri().toString(), id);
+ }
+ record.data = object;
+ }
+
+ public Object readRecord(SCAObject owner, String id) {
+ Map<String, Record> map = store.get(owner);
+ if (map == null) {
+ return null;
+ }
+ Record record = map.get(id);
+ if (record != null) {
+ return record.data;
+ }
+ return null;
+ }
+
+ public void removeRecords() {
+ store.clear();
+ }
+
+ public void removeRecord(SCAObject owner, String id) throws StoreWriteException {
+ Map<String, Record> map = store.get(owner);
+ if (map == null) {
+ throw new StoreWriteException("Owner not found", owner.getUri().toString(), id);
+ }
+ if (map.remove(id) == null) {
+ throw new StoreWriteException("Owner not found", owner.getUri().toString(), id);
+ }
+ }
+
+ public void recover(RecoveryListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ private class Record {
+ private Object data;
+ private long expiration = NEVER;
+
+ public Record(Object data, long expiration) {
+ this.data = data;
+ this.expiration = expiration;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public long getExpiration() {
+ return expiration;
+ }
+ }
+
+ private class Reaper implements Runnable {
+
+ public void run() {
+ long now = System.currentTimeMillis();
+ for (Map.Entry<SCAObject, Map<String, Record>> entries : store.entrySet()) {
+ for (Map.Entry<String, Record> entry : entries.getValue().entrySet()) {
+ final long expiration = entry.getValue().expiration;
+ if (expiration != NEVER && now >= expiration) {
+ SCAObject owner = entries.getKey();
+ Object instance = entry.getValue().getData();
+ // notify listeners of the expiration
+ StoreExpirationEvent event = new StoreExpirationEvent(this, owner, instance);
+ publish(event);
+ entries.getValue().remove(entry.getKey());
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java
new file mode 100644
index 0000000000..79b7bf4ca1
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java
@@ -0,0 +1,206 @@
+/*
+ * 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.core.services.work.jca;
+
+import javax.resource.spi.work.Work;
+import javax.resource.spi.work.WorkEvent;
+import javax.resource.spi.work.WorkException;
+import javax.resource.spi.work.WorkListener;
+import javax.resource.spi.work.WorkManager;
+import javax.resource.spi.work.WorkRejectedException;
+
+import org.apache.tuscany.spi.services.work.NotificationListener;
+import org.apache.tuscany.spi.services.work.WorkScheduler;
+import org.apache.tuscany.spi.services.work.WorkSchedulerException;
+
+/**
+ * A work scheduler implementation based on the JCA SPI work manager.
+ * <p/>
+ * <p/>
+ * This needs a JCA SPI work manager implementation available for scheduling work. Instances can be configured with a
+ * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work
+ * manager implementaion available. </p>
+ */
+public class JcaWorkScheduler implements WorkScheduler {
+
+ /**
+ * Underlying JCA work manager
+ */
+ private WorkManager jcaWorkManager;
+
+ /**
+ * Initializes the JCA work manager.
+ *
+ * @param jcaWorkManager JCA work manager.
+ */
+ public JcaWorkScheduler(WorkManager jcaWorkManager) {
+
+ if (jcaWorkManager == null) {
+ throw new IllegalArgumentException("Work manager cannot be null");
+ }
+ this.jcaWorkManager = jcaWorkManager;
+
+ }
+
+ /**
+ * Schedules a unit of work for future execution. The notification listener is used to register interest in
+ * callbacks regarding the status of the work.
+ *
+ * @param work The unit of work that needs to be asynchronously executed.
+ */
+ public <T extends Runnable> void scheduleWork(T work) {
+ scheduleWork(work, null);
+ }
+
+ /**
+ * Schedules a unit of work for future execution. The notification listener is used to register interest in
+ * callbacks regarding the status of the work.
+ *
+ * @param work The unit of work that needs to be asynchronously executed.
+ * @param listener Notification listener for callbacks.
+ */
+ public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) {
+
+ if (work == null) {
+ throw new IllegalArgumentException("Work cannot be null");
+ }
+
+ JcaWork<T> jcaWork = new JcaWork<T>(work);
+ try {
+ if (listener == null) {
+ jcaWorkManager.scheduleWork(jcaWork);
+ } else {
+ JcaWorkListener<T> jcaWorkListener = new JcaWorkListener<T>(listener);
+ // TODO Clarify the usage of timeout and execution context
+ jcaWorkManager.scheduleWork(jcaWork, -1, null, jcaWorkListener);
+ }
+ } catch (WorkRejectedException ex) {
+ if (listener != null) {
+ listener.workRejected(work);
+ } else {
+ throw new WorkSchedulerException(ex);
+ }
+ } catch (WorkException ex) {
+ throw new WorkSchedulerException(ex);
+ }
+
+ }
+
+ /*
+ * Worklistener for keeping track of work status callbacks.
+ *
+ */
+ private class JcaWorkListener<T extends Runnable> implements WorkListener {
+
+ // Notification listener
+ private NotificationListener<T> listener;
+
+ /*
+ * Initializes the notification listener.
+ */
+ public JcaWorkListener(NotificationListener<T> listener) {
+ this.listener = listener;
+ }
+
+ /*
+ * Callback when the work is accepted.
+ */
+ public void workAccepted(WorkEvent workEvent) {
+ T work = getWork(workEvent);
+ listener.workAccepted(work);
+ }
+
+ /*
+ * Callback when the work is rejected.
+ */
+ public void workRejected(WorkEvent workEvent) {
+ T work = getWork(workEvent);
+ listener.workRejected(work);
+ }
+
+ /*
+ * Callback when the work is started.
+ */
+ public void workStarted(WorkEvent workEvent) {
+ T work = getWork(workEvent);
+ listener.workStarted(work);
+ }
+
+ /*
+ * Callback when the work is completed.
+ */
+ public void workCompleted(WorkEvent workEvent) {
+ T work = getWork(workEvent);
+ Exception exception = workEvent.getException();
+ if (exception != null) {
+ listener.workFailed(work, exception);
+ } else {
+ listener.workCompleted(work);
+ }
+ }
+
+ /*
+ * Gets the underlying work from the work event.
+ */
+ @SuppressWarnings("unchecked")
+ private T getWork(WorkEvent workEvent) {
+ JcaWork<T> jcaWork = (JcaWork<T>) workEvent.getWork();
+ return jcaWork.getWork();
+ }
+
+ }
+
+ /*
+ * JCA work wrapper.
+ */
+ private class JcaWork<T extends Runnable> implements Work {
+
+ // Work that is being executed.
+ private T work;
+
+ /*
+ * Initializes the work instance.
+ */
+ public JcaWork(T work) {
+ this.work = work;
+ }
+
+ /*
+ * Releases the work.
+ */
+ public void release() {
+ }
+
+ /*
+ * Performs the work.
+ */
+ public void run() {
+ work.run();
+ }
+
+ /*
+ * Returns the completed work.
+ */
+ public T getWork() {
+ return work;
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java
new file mode 100644
index 0000000000..401960c287
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java
@@ -0,0 +1,217 @@
+/*
+ * 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.core.services.work.jsr237;
+
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Scope;
+
+import org.apache.tuscany.spi.services.work.NotificationListener;
+import org.apache.tuscany.spi.services.work.WorkScheduler;
+import org.apache.tuscany.spi.services.work.WorkSchedulerException;
+
+import commonj.work.Work;
+import commonj.work.WorkEvent;
+import commonj.work.WorkException;
+import commonj.work.WorkListener;
+import commonj.work.WorkManager;
+import commonj.work.WorkRejectedException;
+
+/**
+ * A work scheduler implementation based on a JSR 237 work manager.
+ * <p/>
+ * <p/>
+ * This needs a JSR 237 work manager implementation available for scheduling work. Instances can be configured with a
+ * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work
+ * manager implementaion available. For example, if the managed environment supports work manager the runtime can use
+ * the appropriate lookup mechanism to inject the work manager implementation. </p>
+ */
+@Scope("COMPOSITE")
+public class Jsr237WorkScheduler implements WorkScheduler {
+
+ /**
+ * Underlying JSR-237 work manager
+ */
+ private WorkManager jsr237WorkManager;
+
+ /**
+ * Initializes the JSR 237 work manager.
+ *
+ * @param jsr237WorkManager JSR 237 work manager.
+ */
+ public Jsr237WorkScheduler(@Reference WorkManager jsr237WorkManager) {
+ if (jsr237WorkManager == null) {
+ throw new IllegalArgumentException("Work manager cannot be null");
+ }
+ this.jsr237WorkManager = jsr237WorkManager;
+ }
+
+ /**
+ * Schedules a unit of work for future execution. The notification listener is used to register interest in
+ * callbacks regarding the status of the work.
+ *
+ * @param work The unit of work that needs to be asynchronously executed.
+ */
+ public <T extends Runnable> void scheduleWork(T work) {
+ scheduleWork(work, null);
+ }
+
+ /**
+ * Schedules a unit of work for future execution. The notification listener is used to register interest in
+ * callbacks regarding the status of the work.
+ *
+ * @param work The unit of work that needs to be asynchronously executed.
+ * @param listener Notification listener for callbacks.
+ */
+ public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) {
+
+ if (work == null) {
+ throw new IllegalArgumentException("Work cannot be null");
+ }
+
+ Jsr237Work<T> jsr237Work = new Jsr237Work<T>(work);
+ try {
+ if (listener == null) {
+ jsr237WorkManager.schedule(jsr237Work);
+ } else {
+ Jsr237WorkListener<T> jsr237WorkListener = new Jsr237WorkListener<T>(listener, work);
+ jsr237WorkManager.schedule(jsr237Work, jsr237WorkListener);
+ }
+ } catch (WorkRejectedException ex) {
+ if (listener != null) {
+ listener.workRejected(work);
+ } else {
+ throw new WorkSchedulerException(ex);
+ }
+ } catch (WorkException ex) {
+ throw new WorkSchedulerException(ex);
+ }
+
+ }
+
+ /*
+ * Worklistener for keeping track of work status callbacks.
+ *
+ */
+ private class Jsr237WorkListener<T extends Runnable> implements WorkListener {
+
+ // Notification listener
+ private NotificationListener<T> listener;
+
+ // Work
+ private T work;
+
+ /*
+ * Initializes the notification listener.
+ */
+ public Jsr237WorkListener(NotificationListener<T> listener, T work) {
+ this.listener = listener;
+ this.work = work;
+ }
+
+ /*
+ * Callback when the work is accepted.
+ */
+ public void workAccepted(WorkEvent workEvent) {
+ T work = getWork();
+ listener.workAccepted(work);
+ }
+
+ /*
+ * Callback when the work is rejected.
+ */
+ public void workRejected(WorkEvent workEvent) {
+ T work = getWork();
+ listener.workRejected(work);
+ }
+
+ /*
+ * Callback when the work is started.
+ */
+ public void workStarted(WorkEvent workEvent) {
+ T work = getWork();
+ listener.workStarted(work);
+ }
+
+ /*
+ * Callback when the work is completed.
+ */
+ public void workCompleted(WorkEvent workEvent) {
+ T work = getWork();
+ Exception exception = workEvent.getException();
+ if (exception != null) {
+ listener.workFailed(work, exception);
+ } else {
+ listener.workCompleted(work);
+ }
+ }
+
+ /*
+ * Gets the underlying work from the work event.
+ */
+ private T getWork() {
+ return work;
+ }
+
+ }
+
+ /*
+ * JCA work wrapper.
+ */
+ private class Jsr237Work<T extends Runnable> implements Work {
+
+ // Work that is being executed.
+ private T work;
+
+ /*
+ * Initializes the work instance.
+ */
+ public Jsr237Work(T work) {
+ this.work = work;
+ }
+
+ /*
+ * Returns the completed work.
+ */
+ public T getWork() {
+ return work;
+ }
+
+ /*
+ * Release the work.
+ */
+ public void release() {
+ }
+
+ /*
+ * Work attributes are not daemon.
+ */
+ public boolean isDaemon() {
+ return false;
+ }
+
+ /*
+ * Runs the work.
+ */
+ public void run() {
+ work.run();
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java
new file mode 100644
index 0000000000..c391d0b597
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.services.work.jsr237.workmanager;
+
+import commonj.work.WorkEvent;
+import commonj.work.WorkException;
+import commonj.work.WorkItem;
+
+/**
+ * Default immutable implementation of the <code>WorkEvent</code> class.
+ */
+class DefaultWorkEvent implements WorkEvent {
+
+ // Work item for this event
+ private WorkItem workItem;
+
+ // Exception if something has gone wrong
+ private WorkException exception;
+
+ /**
+ * Instantiates the event.
+ *
+ * @param workItem Work item for this event.
+ */
+ public DefaultWorkEvent(final DefaultWorkItem workItem) {
+ this.workItem = workItem;
+ this.exception = workItem.getException();
+ }
+
+ /**
+ * Returns the work type based on whether the work was accepted, started,
+ * rejected or completed.
+ *
+ * @return Work type.
+ */
+ public int getType() {
+ return workItem.getStatus();
+ }
+
+ /**
+ * Returns the work item associated with this work type.
+ *
+ * @return Work item.
+ */
+ public WorkItem getWorkItem() {
+ return workItem;
+ }
+
+ /**
+ * Returns the exception if the work completed with an exception.
+ *
+ * @return Work exception.
+ */
+ public WorkException getException() {
+ return exception;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java
new file mode 100644
index 0000000000..0adc005bb0
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java
@@ -0,0 +1,166 @@
+/*
+ * 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.core.services.work.jsr237.workmanager;
+
+import commonj.work.Work;
+import commonj.work.WorkException;
+import commonj.work.WorkItem;
+
+/**
+ * An identity based immutable implementation of the <code>WorkItem</code>
+ * interface.
+ *
+ */
+class DefaultWorkItem implements WorkItem {
+
+ // Id scoped for the VM
+ private String id;
+
+ // Status
+ private int status = -1;
+
+ // Result
+ private Work result;
+
+ // Original work
+ private Work originalWork;
+
+ // Exception
+ private WorkException exception;
+
+ /**
+ * Instantiates an id for this item.
+ *
+ * @param id of this work event.
+ */
+ protected DefaultWorkItem(final String id, final Work orginalWork) {
+ this.id = id;
+ this.originalWork = orginalWork;
+ }
+
+ /**
+ * Returns the id.
+ *
+ * @return Id of this item.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the original work.
+ *
+ * @return Original work.
+ */
+ public Work getOriginalWork() {
+ return originalWork;
+ }
+
+ /**
+ * Returns the work result if the work completed.
+ *
+ * @return Work.
+ * @throws WorkException If the work completed with an exception.
+ */
+ public Work getResult() throws WorkException {
+ return result;
+ }
+
+ /**
+ * Sets the result.
+ *
+ * @param result Result.
+ */
+ protected void setResult(final Work result) {
+ this.result = result;
+ }
+
+ /**
+ * Returns the exception if work completed with an exception.
+ *
+ * @return Work exception.
+ */
+ protected WorkException getException() {
+ return exception;
+ }
+
+ /**
+ * Sets the exception.
+ *
+ * @param exception Exception.
+ */
+ protected void setException(final WorkException exception) {
+ this.exception = exception;
+ }
+
+ /**
+ * Returns the work type based on whether the work was accepted, started,
+ * rejected or completed.
+ *
+ * @return Work status.
+ */
+ public int getStatus() {
+ return status;
+ }
+
+ /**
+ * Sets the status.
+ *
+ * @param status Status.
+ */
+ protected void setStatus(final int status) {
+ this.status = status;
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ *
+ * @param obj Object to be compared.
+ * @return true if this object is the same as the obj argument; false
+ * otherwise..
+ */
+ public boolean equals(final Object obj) {
+ return (obj != null) && (obj.getClass() == DefaultWorkItem.class) && ((DefaultWorkItem) obj).id.equals(id);
+ }
+
+ /**
+ * Compares this object with the specified object for order. Returns a
+ * negative integer, zero, or a positive integer as this object is less
+ * than, equal to, or greater than the specified object.
+ *
+ * @param o Object to be compared.
+ * @return A negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ * @throws ClassCastException needs better documentation.
+ */
+ public int compareTo(final Object o) {
+ if (o.getClass() != DefaultWorkItem.class) {
+ throw new ClassCastException(o.getClass().getName());
+ } else {
+ return ((DefaultWorkItem) o).getId().compareTo(getId());
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java
new file mode 100644
index 0000000000..1a7639b41d
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.services.work.jsr237.workmanager;
+
+import java.rmi.server.UID;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.Property;
+
+import commonj.work.Work;
+import commonj.work.WorkEvent;
+import commonj.work.WorkException;
+import commonj.work.WorkItem;
+import commonj.work.WorkListener;
+import commonj.work.WorkManager;
+import commonj.work.WorkRejectedException;
+
+/**
+ * A thread-pool based implementation for the JSR-237 work manager.
+ * <p/>
+ * <p/>
+ * This implementation supports only local work.
+ * <p/>
+ * TODO Elaborate the implementation. </p>
+ */
+public class ThreadPoolWorkManager implements WorkManager {
+
+ // Map of work items currently handled by the work manager
+ private Map<DefaultWorkItem, WorkListener> workItems = new ConcurrentHashMap<DefaultWorkItem, WorkListener>();
+
+ // Thread-pool
+ private ExecutorService executor;
+
+ /**
+ * Initializes the thread-pool.
+ *
+ * @param threadPoolSize Thread-pool size.
+ */
+ public ThreadPoolWorkManager(@Property(name = "poolSize") int threadPoolSize) {
+ executor = Executors.newFixedThreadPool(threadPoolSize);
+ }
+
+ /**
+ * Schedules a unit of work asynchronously.
+ *
+ * @param work Work that needs to be scheduled.
+ * @return Work Work item representing the asynchronous work
+ */
+ public WorkItem schedule(Work work) throws WorkException {
+ return schedule(work, null);
+ }
+
+ /**
+ * Schedules a unit of work asynchronously.
+ *
+ * @param work Work that needs to be scheduled.
+ * @param workListener Work listener for callbacks.
+ * @return Work Work item representing the asynchronous work
+ */
+ public WorkItem schedule(Work work, WorkListener workListener) throws WorkRejectedException {
+
+ DefaultWorkItem workItem = new DefaultWorkItem(new UID().toString(), work);
+ if (workListener != null) {
+ workItems.put(workItem, workListener);
+ }
+ workAccepted(workItem, work);
+ if (scheduleWork(work, workItem)) {
+ return workItem;
+ } else {
+ workItem.setStatus(WorkEvent.WORK_REJECTED);
+ if (workListener != null) {
+ workListener.workRejected(new DefaultWorkEvent(workItem));
+ }
+ throw new WorkRejectedException("Unable to schedule work");
+ }
+ }
+
+ /**
+ * Wait for all the specified units of work to finish.
+ *
+ * @param works Units of the work that need to finish.
+ * @param timeout Timeout for waiting for the units of work to finish.
+ */
+ public boolean waitForAll(Collection works, long timeout) {
+ throw new UnsupportedOperationException("waitForAll not supported");
+ }
+
+ /**
+ * Wait for any of the specified units of work to finish.
+ *
+ * @param works Units of the work that need to finish.
+ * @param timeout Timeout for waiting for the units of work to finish.
+ */
+ public Collection waitForAny(Collection works, long timeout) {
+ throw new UnsupportedOperationException("waitForAny not supported");
+ }
+
+ /**
+ * Method provided for subclasses to indicate a work accptance.
+ *
+ * @param workItem Work item representing the work that was accepted.
+ * @param work Work that was accepted.
+ */
+ private void workAccepted(final DefaultWorkItem workItem, final Work work) {
+ WorkListener listener = workItems.get(workItem);
+ if (listener != null) {
+ workItem.setStatus(WorkEvent.WORK_ACCEPTED);
+ WorkEvent event = new DefaultWorkEvent(workItem);
+ listener.workAccepted(event);
+ }
+ }
+
+ /*
+ * Method to indicate a work start.
+ */
+ private void workStarted(final DefaultWorkItem workItem, final Work work) {
+ WorkListener listener = workItems.get(workItem);
+ if (listener != null) {
+ workItem.setStatus(WorkEvent.WORK_STARTED);
+ WorkEvent event = new DefaultWorkEvent(workItem);
+ listener.workStarted(event);
+ }
+ }
+
+ /*
+ * Method to indicate a work completion.
+ */
+ private void workCompleted(final DefaultWorkItem workItem, final Work work) {
+ workCompleted(workItem, work, null);
+ }
+
+ /*
+ * Method to indicate a work completion.
+ */
+ private void workCompleted(final DefaultWorkItem workItem, final Work work, final WorkException exception) {
+ WorkListener listener = workItems.get(workItem);
+ if (listener != null) {
+ workItem.setStatus(WorkEvent.WORK_COMPLETED);
+ workItem.setResult(work);
+ workItem.setException(exception);
+ WorkEvent event = new DefaultWorkEvent(workItem);
+ listener.workCompleted(event);
+ workItems.remove(workItem);
+ }
+ }
+
+ /*
+ * Schedules the work using the threadpool.
+ */
+ private boolean scheduleWork(final Work work, final DefaultWorkItem workItem) {
+ try {
+ executor.execute(new DecoratingWork(workItem, work));
+ return true;
+ } catch (RejectedExecutionException ex) {
+ return false;
+ }
+ }
+
+ /*
+ * Class that decorates the original worker so that it can get callbacks when work is done.
+ */
+ private final class DecoratingWork implements Runnable {
+
+ // Work item for this work.
+ private DefaultWorkItem workItem;
+
+ // The original work.
+ private Work decoratedWork;
+
+ /*
+ * Initializes the work item and underlying work.
+ */
+ private DecoratingWork(final DefaultWorkItem workItem, final Work decoratedWork) {
+ this.workItem = workItem;
+ this.decoratedWork = decoratedWork;
+ }
+
+ /*
+ * Overrides the run method.
+ */
+ public void run() {
+ workStarted(workItem, decoratedWork);
+ try {
+ decoratedWork.run();
+ workCompleted(workItem, decoratedWork);
+ } catch (Throwable th) {
+ workCompleted(workItem, decoratedWork, new WorkException(th.getMessage(), th));
+ }
+ }
+
+ }
+
+ @Destroy
+ public void destroy() {
+ executor.shutdown();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java
new file mode 100644
index 0000000000..e79ea7a74a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java
@@ -0,0 +1,285 @@
+/*
+ * 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.core.util;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+
+public class FileHelper {
+ /**
+ * The extension separator character.
+ */
+ private static final char EXTENSION_SEPARATOR = '.';
+
+ /**
+ * The Unix separator character.
+ */
+ private static final char UNIX_SEPARATOR = '/';
+
+ /**
+ * The Windows separator character.
+ */
+ private static final char WINDOWS_SEPARATOR = '\\';
+
+ protected FileHelper() {
+
+ }
+ /**
+ * Returns the index of the last directory separator character.
+ * <p>
+ * This method will handle a file in either Unix or Windows format.
+ * The position of the last forward or backslash is returned.
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
+ *
+ * @param filename the filename to find the last path separator in, null returns -1
+ * @return the index of the last separator character, or -1 if there
+ * is no such character
+ */
+ public static int indexOfLastSeparator(String filename) {
+ if (filename == null) {
+ return -1;
+ }
+ int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
+ int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
+ return Math.max(lastUnixPos, lastWindowsPos);
+ }
+
+ /**
+ * Returns the index of the last extension separator character, which is a dot.
+ * <p>
+ * This method also checks that there is no directory separator after the last dot.
+ * To do this it uses {@link #indexOfLastSeparator(String)} which will
+ * handle a file in either Unix or Windows format.
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
+ *
+ * @param filename the filename to find the last path separator in, null returns -1
+ * @return the index of the last separator character, or -1 if there
+ * is no such character
+ */
+ public static int indexOfExtension(String filename) {
+ if (filename == null) {
+ return -1;
+ }
+ int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
+ int lastSeparator = indexOfLastSeparator(filename);
+ return lastSeparator > extensionPos ? -1 : extensionPos;
+ }
+
+ /**
+ * Gets the name minus the path from a full filename.
+ * <p>
+ * This method will handle a file in either Unix or Windows format.
+ * The text after the last forward or backslash is returned.
+ * <pre>
+ * a/b/c.txt --> c.txt
+ * a.txt --> a.txt
+ * a/b/c --> c
+ * a/b/c/ --> ""
+ * </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
+ *
+ * @param fileName the filename to query, null returns null
+ * @return the name of the file without the path, or an empty string if none exists
+ */
+ public static String getName(String fileName) {
+ if (fileName == null) {
+ return null;
+ }
+ int index = indexOfLastSeparator(fileName);
+ return fileName.substring(index + 1);
+ }
+
+ /**
+ * Gets the extension of a filename.
+ * <p>
+ * This method returns the textual part of the filename after the last dot.
+ * There must be no directory separator after the dot.
+ * <pre>
+ * foo.txt --> "txt"
+ * a/b/c.jpg --> "jpg"
+ * a/b.txt/c --> ""
+ * a/b/c --> ""
+ * </pre>
+ * <p>
+ * The output will be the same irrespective of the machine that the code is running on.
+ *
+ * @param filename the filename to retrieve the extension of.
+ * @return the extension of the file or an empty string if none exists.
+ */
+ public static String getExtension(String filename) {
+ if (filename == null) {
+ return null;
+ }
+ int index = indexOfExtension(filename);
+ if (index == -1) {
+ return "";
+ } else {
+ return filename.substring(index + 1);
+ }
+ }
+
+ /**
+ * Make a directory, including any necessary but nonexistent parent
+ * directories. If there already exists a file with specified name or
+ * the directory cannot be created then an exception is thrown.
+ *
+ * @param directory directory to create, not null
+ * @throws NullPointerException if the directory is null
+ * @throws IOException if the directory cannot be created
+ */
+ public static void forceMkdir(File directory) throws IOException {
+ if (directory.exists()) {
+ if (directory.isFile()) {
+ String message =
+ "File "
+ + directory
+ + " exists and is "
+ + "not a directory. Unable to create directory.";
+ throw new IOException(message);
+ }
+ } else {
+ if (!directory.mkdirs()) {
+ String message =
+ "Unable to create directory " + directory;
+ throw new IOException(message);
+ }
+ }
+ }
+
+ /**
+ * Delete a file. If file is a directory, delete it and all sub-directories.
+ * <p>
+ * The difference between File.delete() and this method are:
+ * <ul>
+ * <li>A directory to be deleted does not have to be empty.</li>
+ * <li>You get exceptions when a file or directory cannot be deleted.
+ * (java.io.File methods returns a boolean)</li>
+ * </ul>
+ *
+ * @param file file or directory to delete, not null
+ * @throws NullPointerException if the directory is null
+ * @throws IOException in case deletion is unsuccessful
+ */
+ public static void forceDelete(File file) throws IOException {
+ if (file.isDirectory()) {
+ deleteDirectory(file);
+ } else {
+ if (!file.exists()) {
+ throw new FileNotFoundException("File does not exist: " + file);
+ }
+ if (!file.delete()) {
+ String message =
+ "Unable to delete file: " + file;
+ throw new IOException(message);
+ }
+ }
+ }
+
+ /**
+ * Recursively delete a directory.
+ *
+ * @param directory directory to delete
+ * @throws IOException in case deletion is unsuccessful
+ */
+ public static void deleteDirectory(File directory)
+ throws IOException {
+ if (!directory.exists()) {
+ return;
+ }
+
+ cleanDirectory(directory);
+ if (!directory.delete()) {
+ String message =
+ "Unable to delete directory " + directory + ".";
+ throw new IOException(message);
+ }
+ }
+
+ /**
+ * Clean a directory without deleting it.
+ *
+ * @param directory directory to clean
+ * @throws IOException in case cleaning is unsuccessful
+ */
+ public static void cleanDirectory(File directory) throws IOException {
+ if (!directory.exists()) {
+ String message = directory + " does not exist";
+ throw new IllegalArgumentException(message);
+ }
+
+ if (!directory.isDirectory()) {
+ String message = directory + " is not a directory";
+ throw new IllegalArgumentException(message);
+ }
+
+ File[] files = directory.listFiles();
+ if (files == null) { // null if security restricted
+ throw new IOException("Failed to list contents of " + directory);
+ }
+
+ IOException exception = null;
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ try {
+ forceDelete(file);
+ } catch (IOException ioe) {
+ exception = ioe;
+ }
+ }
+
+ if (null != exception) {
+ throw exception;
+ }
+ }
+
+ /**
+ * Convert from a <code>URL</code> to a <code>File</code>.
+ * <p>
+ * From version 1.1 this method will decode the URL.
+ * Syntax such as <code>file:///my%20docs/file.txt</code> will be
+ * correctly decoded to <code>/my docs/file.txt</code>.
+ *
+ * @param url the file URL to convert, null returns null
+ * @return the equivalent <code>File</code> object, or <code>null</code>
+ * if the URL's protocol is not <code>file</code>
+ * @throws IllegalArgumentException if the file is incorrectly encoded
+ */
+ public static File toFile(URL url) {
+ if (url == null || !url.getProtocol().equals("file")) {
+ return null;
+ } else {
+ String filename = url.getFile().replace('/', File.separatorChar);
+ int pos = 0;
+ while ((pos = filename.indexOf('%', pos)) >= 0) { // NOPMD
+ if (pos + 2 < filename.length()) {
+ String hexStr = filename.substring(pos + 1, pos + 3);
+ char ch = (char) Integer.parseInt(hexStr, 16);
+ filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
+ }
+ }
+ return new File(filename);
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java
new file mode 100644
index 0000000000..bb504ef57e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java
@@ -0,0 +1,94 @@
+/*
+ * 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.core.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class IOHelper {
+ /**
+ * The default buffer size to use.
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ protected IOHelper() {
+
+ }
+
+ /**
+ * Unconditionally close an <code>InputStream</code>.
+ * <p/>
+ * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. This is typically used in
+ * finally blocks.
+ *
+ * @param input the InputStream to close, may be null or already closed
+ */
+ public static void closeQuietly(InputStream input) {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+
+ /**
+ * Unconditionally close an <code>OutputStream</code>.
+ * <p/>
+ * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. This is typically used in
+ * finally blocks.
+ *
+ * @param output the OutputStream to close, may be null or already closed
+ */
+ public static void closeQuietly(OutputStream output) {
+ try {
+ if (output != null) {
+ output.close();
+ }
+ } catch (IOException ioe) {
+ // ignore
+ }
+ }
+
+ /**
+ * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>.
+ * <p/>
+ * This method buffers the input internally, so there is no need to use a <code>BufferedInputStream</code>.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since Commons IO 1.1
+ */
+ public static int copy(InputStream input, OutputStream output) throws IOException {
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ int count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) { //NOPMD
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java
new file mode 100644
index 0000000000..6b11725481
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java
@@ -0,0 +1,439 @@
+/*
+ * 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.core.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implements various reflection-related operations
+ *
+ * @version $Rev$ $Date$
+ */
+public final class JavaIntrospectionHelper {
+
+ private static final Class[] EMPTY_CLASS_ARRY = new Class[0];
+
+ /**
+ * Hide the constructor
+ */
+ private JavaIntrospectionHelper() {
+ }
+
+
+ /**
+ * Returns a collection of public, and protected fields declared by a class or one of its supertypes
+ */
+ public static Set<Field> getAllPublicAndProtectedFields(Class clazz) {
+ return getAllPublicAndProtectedFields(clazz, new HashSet<Field>());
+ }
+
+ /**
+ * Recursively evaluates the type hierachy to return all fields that are public or protected
+ */
+ private static Set<Field> getAllPublicAndProtectedFields(Class clazz, Set<Field> fields) {
+ if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) {
+ return fields;
+ }
+ fields = getAllPublicAndProtectedFields(clazz.getSuperclass(), fields);
+ Field[] declaredFields = clazz.getDeclaredFields();
+ for (Field field : declaredFields) {
+ int modifiers = field.getModifiers();
+ if ((Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) && !Modifier.isStatic(modifiers)) {
+ field.setAccessible(true); // ignore Java accessibility
+ fields.add(field);
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * Returns a collection of public and protected methods declared by a class or one of its supertypes. Note that
+ * overriden methods will not be returned in the collection (i.e. only the method override will be). <p/> This
+ * method can potentially be expensive as reflection information is not cached. It is assumed that this method will
+ * be used during a configuration phase.
+ */
+ public static Set<Method> getAllUniquePublicProtectedMethods(Class clazz) {
+ return getAllUniqueMethods(clazz, new HashSet<Method>());
+ }
+
+ /**
+ * Recursively evaluates the type hierarchy to return all unique methods
+ */
+ private static Set<Method> getAllUniqueMethods(Class pClass, Set<Method> methods) {
+ if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) {
+ return methods;
+ }
+ // we first evaluate methods of the subclass and then move to the parent
+ Method[] declaredMethods = pClass.getDeclaredMethods();
+ for (Method declaredMethod : declaredMethods) {
+ int modifiers = declaredMethod.getModifiers();
+ if ((!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers)) || Modifier.isStatic(modifiers)) {
+ continue;
+ }
+ if (methods.size() == 0) {
+ methods.add(declaredMethod);
+ } else {
+ List<Method> temp = new ArrayList<Method>();
+ boolean matched = false;
+ for (Method method : methods) {
+ // only add if not already in the set from a supclass (i.e. the
+ // method is not overrided)
+ if (exactMethodMatch(declaredMethod, method)) {
+ matched = true;
+ break;
+ }
+ }
+ if (!matched) {
+ // TODO ignore Java accessibility
+ declaredMethod.setAccessible(true);
+ temp.add(declaredMethod);
+ }
+ methods.addAll(temp);
+ temp.clear();
+ }
+ }
+ // evaluate class hierarchy - this is done last to track inherited methods
+ methods = getAllUniqueMethods(pClass.getSuperclass(), methods);
+ return methods;
+ }
+
+ /**
+ * Finds the closest matching field with the given name, that is, a field of the exact specified type or,
+ * alternately, of a supertype.
+ *
+ * @param name the name of the field
+ * @param type the field type
+ * @param fields the collection of fields to search
+ * @return the matching field or null if not found
+ */
+ public static Field findClosestMatchingField(String name, Class type, Set<Field> fields) {
+ Field candidate = null;
+ for (Field field : fields) {
+ if (field.getName().equals(name)) {
+ if (field.getType().equals(type)) {
+ return field; // exact match
+ } else if (field.getType().isAssignableFrom(type)
+ || (field.getType().isPrimitive() && primitiveAssignable(field.getType(), type))) {
+ // We could have the situation where a field parameter is a primitive and the demarshalled value is
+ // an object counterpart (e.g. Integer and int)
+ // @spec issue
+ // either an interface or super class, so keep a reference until
+ // we know there are no closer types
+ candidate = field;
+ }
+ }
+ }
+ if (candidate != null) {
+ return candidate;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Finds the closest matching method with the given name, that is, a method taking the exact parameter types or,
+ * alternately, parameter supertypes.
+ *
+ * @param name the name of the method
+ * @param types the method parameter types
+ * @param methods the collection of methods to search
+ * @return the matching method or null if not found
+ */
+ public static Method findClosestMatchingMethod(String name, Class[] types, Set<Method> methods) {
+ if (types == null) {
+ types = EMPTY_CLASS_ARRY;
+ }
+ Method candidate = null;
+ for (Method method : methods) {
+ if (method.getName().equals(name) && method.getParameterTypes().length == types.length) {
+ Class<?>[] params = method.getParameterTypes();
+ boolean disqualify = false;
+ boolean exactMatch = true;
+ for (int i = 0; i < params.length; i++) {
+ if (!params[i].equals(types[i]) && !params[i].isAssignableFrom(types[i])) {
+ // no match
+ disqualify = true;
+ exactMatch = false;
+ break;
+ } else if (!params[i].equals(types[i]) && params[i].isAssignableFrom(types[i])) {
+ // not exact match
+ exactMatch = false;
+ }
+ }
+ if (disqualify) {
+ continue;
+ } else if (exactMatch) {
+ return method;
+ } else {
+ candidate = method;
+ }
+ }
+ }
+ if (candidate != null) {
+ return candidate;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Searches a collection of fields for one that matches by name and has a multiplicity type. i.e. a List or Array of
+ * interfaces
+ *
+ * @return a matching field or null
+ */
+ public static Field findMultiplicityFieldByName(String name, Set<Field> fields) {
+ for (Field candidate : fields) {
+ if (candidate.getName().equals(name)
+ && (List.class.isAssignableFrom(candidate.getType()) || (candidate.getType().isArray()
+ && candidate.getType().getComponentType() != null && candidate.getType().getComponentType()
+ .isInterface()))) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Searches a collection of method for one that matches by name and has single parameter of a multiplicity type.
+ * i.e. a List or Array of interfaces
+ *
+ * @return a matching method or null
+ */
+ public static Method findMultiplicityMethodByName(String name, Set<Method> methods) {
+ for (Method candidate : methods) {
+ if (candidate.getName().equals(name)
+ && candidate.getParameterTypes().length == 1
+ && (List.class.isAssignableFrom(candidate.getParameterTypes()[0])
+ || (candidate.getParameterTypes()[0].isArray()
+ && candidate.getParameterTypes()[0].getComponentType() != null
+ && candidate.getParameterTypes()[0].getComponentType().isInterface()))) {
+ return candidate;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Determines if two methods "match" - that is, they have the same method names and exact parameter types (one is
+ * not a supertype of the other)
+ */
+ public static boolean exactMethodMatch(Method method1, Method method2) {
+ if (!method1.getName().equals(method2.getName())) {
+ return false;
+ }
+ Class[] types1 = method1.getParameterTypes();
+ Class[] types2 = method2.getParameterTypes();
+ if (types1.length == 0 && types2.length == 0) {
+ return true;
+ } else if (types1.length == types2.length) {
+ for (int n = 0; n < types1.length; n++) {
+ if (!types1[n].equals(types2[n])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException {
+ return clazz.getConstructor((Class[]) null);
+ }
+
+ /**
+ * Loads a class corresponding to the class name using the current context class loader.
+ *
+ * @throws ClassNotFoundException if the class was not found on the classpath
+ */
+ public static Class loadClass(String pName) throws ClassNotFoundException {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ return Class.forName(pName, true, loader);
+ }
+
+ /**
+ * Returns the simple name of a class - i.e. the class name devoid of its package qualifier
+ *
+ * @param implClass the implmentation class
+ */
+ public static String getBaseName(Class<?> implClass) {
+ String baseName = implClass.getName();
+ int lastDot = baseName.lastIndexOf('.');
+ if (lastDot != -1) {
+ baseName = baseName.substring(lastDot + 1);
+ }
+ return baseName;
+ }
+
+ public static boolean isImmutable(Class clazz) {
+ return String.class == clazz
+ || clazz.isPrimitive()
+ || Number.class.isAssignableFrom(clazz)
+ || Boolean.class.isAssignableFrom(clazz)
+ || Character.class.isAssignableFrom(clazz)
+ || Byte.class.isAssignableFrom(clazz);
+ }
+
+ /**
+ * Takes a property name and converts it to a getter method name according to JavaBean conventions. For example,
+ * property <code>foo<code> is returned as <code>getFoo</code>
+ */
+ public static String toGetter(String name) {
+ return "get" + name.toUpperCase().substring(0, 1) + name.substring(1);
+ }
+
+ /**
+ * Takes a setter or getter method name and converts it to a property name according to JavaBean conventions. For
+ * example, <code>setFoo(var)</code> is returned as property <code>foo<code>
+ */
+ public static String toPropertyName(String name) {
+ if (!name.startsWith("set")) {
+ return name;
+ }
+ return Character.toLowerCase(name.charAt(3)) + name.substring(4);
+ }
+
+ /**
+ * Takes a property name and converts it to a setter method name according to JavaBean conventions. For example, the
+ * property <code>foo<code> is returned as <code>setFoo(var)</code>
+ */
+ public static String toSetter(String name) {
+ return "set" + name.toUpperCase().substring(0, 1) + name.substring(1);
+ }
+
+ /**
+ * Compares a two types, assuming one is a primitive, to determine if the other is its object counterpart
+ */
+ private static boolean primitiveAssignable(Class memberType, Class param) {
+ if (memberType == Integer.class) {
+ return param == Integer.TYPE;
+ } else if (memberType == Double.class) {
+ return param == Double.TYPE;
+ } else if (memberType == Float.class) {
+ return param == Float.TYPE;
+ } else if (memberType == Short.class) {
+ return param == Short.TYPE;
+ } else if (memberType == Character.class) {
+ return param == Character.TYPE;
+ } else if (memberType == Boolean.class) {
+ return param == Boolean.TYPE;
+ } else if (memberType == Byte.class) {
+ return param == Byte.TYPE;
+ } else if (param == Integer.class) {
+ return memberType == Integer.TYPE;
+ } else if (param == Double.class) {
+ return memberType == Double.TYPE;
+ } else if (param == Float.class) {
+ return memberType == Float.TYPE;
+ } else if (param == Short.class) {
+ return memberType == Short.TYPE;
+ } else if (param == Character.class) {
+ return memberType == Character.TYPE;
+ } else if (param == Boolean.class) {
+ return memberType == Boolean.TYPE;
+ } else if (param == Byte.class) {
+ return memberType == Byte.TYPE;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the generic types represented in the given type. Usage as follows: <code>
+ * JavaIntrospectionHelper.getGenerics(field.getGenericType());
+ * <p/>
+ * JavaIntrospectionHelper.getGenerics(m.getGenericParameterTypes()[0];); </code>
+ *
+ * @return the generic types in order of declaration or an empty array if the type is not genericized
+ */
+ public static List<? extends Type> getGenerics(Type genericType) {
+ List<Type> classes = new ArrayList<Type>();
+ if (genericType instanceof ParameterizedType) {
+ ParameterizedType ptype = (ParameterizedType) genericType;
+ // get the type arguments
+ Type[] targs = ptype.getActualTypeArguments();
+ for (Type targ : targs) {
+ classes.add(targ);
+ }
+ }
+ return classes;
+ }
+
+ /**
+ * Returns the generic type specified by the class at the given position as in:
+ * <p/>
+ * <code> public class Foo<Bar,Baz>{ //.. }
+ * <p/>
+ * JavaIntrospectionHelper.introspectGeneric(Foo.class,1); <code>
+ * <p/>
+ * will return Baz.
+ */
+ public static Class introspectGeneric(Class<?> clazz, int pos) {
+ assert clazz != null : "No class specified";
+ Type type = clazz.getGenericSuperclass();
+ if (type instanceof ParameterizedType) {
+ Type[] args = ((ParameterizedType) type).getActualTypeArguments();
+ if (args.length <= pos) {
+ throw new IllegalArgumentException("Invalid index value for generic class " + clazz.getName());
+ }
+ return (Class) ((ParameterizedType) type).getActualTypeArguments()[pos];
+ } else {
+ Type[] interfaces = clazz.getGenericInterfaces();
+ for (Type itype : interfaces) {
+ if (!(itype instanceof ParameterizedType)) {
+ continue;
+ }
+ ParameterizedType interfaceType = (ParameterizedType) itype;
+ return (Class) interfaceType.getActualTypeArguments()[0];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the set of interfaces implemented by the given class and its ancestors or a blank set if none
+ */
+ public static Set<Class> getAllInterfaces(Class clazz) {
+ Set<Class> implemented = new HashSet<Class>();
+ getAllInterfaces(clazz, implemented);
+ return implemented;
+ }
+
+ private static void getAllInterfaces(Class clazz, Set<Class> implemented) {
+ Class[] interfaces = clazz.getInterfaces();
+ for (Class interfaze : interfaces) {
+ implemented.add(interfaze);
+ }
+ Class<?> superClass = clazz.getSuperclass();
+ // Object has no superclass so check for null
+ if (superClass != null && !superClass.equals(Object.class)) {
+ getAllInterfaces(superClass, implemented);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java
new file mode 100644
index 0000000000..c0bf7780f5
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.wire;
+
+import org.osoa.sca.NoRegisteredCallbackException;
+
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.Message;
+
+/**
+ * An interceptor applied to the forward direction of a wire that ensures the callback target implements the required
+ * service contract. This is required as callback targets may be set dynamically by service implementations.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CallbackInterfaceInterceptor implements Interceptor {
+ private boolean invokingServiceImplements;
+ private Interceptor next;
+
+ public CallbackInterfaceInterceptor(boolean invokingServiceImplements) {
+ this.invokingServiceImplements = invokingServiceImplements;
+ }
+
+ public Message invoke(Message msg) {
+ // TODO check in the context if a callback object is set, if so invoke next since the setCallback will
+ // perform the check
+ if (!invokingServiceImplements) {
+ throw new NoRegisteredCallbackException("Callback target does not implement the callback interface");
+ }
+ return next.invoke(msg);
+ }
+
+ public void setNext(Interceptor next) {
+ this.next = next;
+ }
+
+ public Interceptor getNext() {
+ return next;
+ }
+
+ public boolean isOptimizable() {
+ return false;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java
new file mode 100644
index 0000000000..d5fca62e1b
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java
@@ -0,0 +1,94 @@
+/*
+ * 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.core.wire;
+
+import java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.IncompatibleServiceContractException;
+
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+
+/**
+ * Formats {@link org.apache.tuscany.spi.wire.IncompatibleServiceContractException} for JDK logging
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class IncompatibleServiceContractExceptionFormatter implements ExceptionFormatter {
+ private FormatterRegistry factory;
+
+ public IncompatibleServiceContractExceptionFormatter(@Reference FormatterRegistry factory) {
+ this.factory = factory;
+ factory.register(this);
+ }
+
+ public boolean canFormat(Class<?> type) {
+ return IncompatibleServiceContractException.class.isAssignableFrom(type);
+ }
+
+ @Destroy
+ public void destroy() {
+ factory.unregister(this);
+ }
+
+ public PrintWriter write(PrintWriter writer, Throwable exception) {
+ assert exception instanceof IncompatibleServiceContractException;
+ IncompatibleServiceContractException e = (IncompatibleServiceContractException) exception;
+ e.appendBaseMessage(writer);
+ ServiceContract<?> source = e.getSource();
+ String sourceContractName = null;
+ if (source != null) {
+ sourceContractName = source.getInterfaceName();
+ }
+ Operation<?> sourceOperation = e.getSourceOperation();
+ String sourceOpName = null;
+ if (sourceOperation != null) {
+ sourceOpName = sourceOperation.getName();
+ }
+ if (sourceOpName == null) {
+ writer.write("\nSource Contract: " + sourceContractName);
+ } else {
+ writer.write("\nSource Contract: " + sourceContractName + "/" + sourceOpName);
+ }
+ ServiceContract<?> target = e.getTarget();
+ String targetContractName = null;
+ if (target != null) {
+ targetContractName = target.getInterfaceName();
+ }
+ Operation<?> targetOperation = e.getTargetOperation();
+ String targetOpName = null;
+ if (targetOperation != null) {
+ targetOpName = targetOperation.getName();
+ }
+ if (targetOpName == null) {
+ writer.write("\nTarget Contract: " + targetContractName + "\n");
+ } else {
+ writer.write("\nTarget Contract: " + targetContractName + "/" + targetOpName + "\n");
+
+ }
+ return writer;
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java
new file mode 100644
index 0000000000..d2e6ec504f
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java
@@ -0,0 +1,95 @@
+/*
+ * 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.core.wire;
+
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.model.Operation;
+
+/**
+ * Default implementation of an invocation chain
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvocationChainImpl implements InvocationChain {
+ protected Operation operation;
+ protected TargetInvoker targetInvoker;
+ protected Interceptor interceptorChainHead;
+ protected Interceptor interceptorChainTail;
+
+ public InvocationChainImpl(Operation operation) {
+ assert operation != null;
+ this.operation = operation;
+ }
+
+ public Operation getOperation() {
+ return operation;
+ }
+
+ public void setTargetInvoker(TargetInvoker invoker) {
+ this.targetInvoker = invoker;
+ }
+
+ public TargetInvoker getTargetInvoker() {
+ return targetInvoker;
+ }
+
+ public void addInterceptor(Interceptor interceptor) {
+ if (interceptorChainHead == null) {
+ interceptorChainHead = interceptor;
+ } else {
+ interceptorChainTail.setNext(interceptor);
+ }
+ interceptorChainTail = interceptor;
+ }
+
+ public void addInterceptor(int index, Interceptor interceptor) {
+ int i = 0;
+ Interceptor next = interceptorChainHead;
+ Interceptor prev = null;
+ while (next != null && i < index) {
+ prev = next;
+ next = next.getNext();
+ i++;
+ }
+ if (i == index) {
+ if (prev != null) {
+ prev.setNext(interceptor);
+ } else {
+ interceptorChainHead = interceptor;
+ }
+ interceptor.setNext(next);
+ if (next == null) {
+ interceptorChainTail = interceptor;
+ }
+ } else {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ }
+
+ public Interceptor getHeadInterceptor() {
+ return interceptorChainHead;
+ }
+
+ public Interceptor getTailInterceptor() {
+ return interceptorChainTail;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java
new file mode 100644
index 0000000000..90b17a930c
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.core.wire;
+
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * Serves as a tail interceptor on a target wire chain. This implementation dispatches to the target invoker passed
+ * inside the wire message. Target invokers are passed from the source in order to allow for caching of target
+ * instances.
+ *
+ * @version $Rev$ $Date$
+ * @see org.apache.tuscany.spi.wire.TargetInvoker
+ */
+public class InvokerInterceptor implements Interceptor {
+
+ public InvokerInterceptor() {
+ }
+
+ public Message invoke(Message msg) throws InvocationRuntimeException {
+ TargetInvoker invoker = msg.getTargetInvoker();
+ if (invoker == null) {
+ throw new InvocationRuntimeException("No target invoker specified on message");
+ }
+ return invoker.invoke(msg);
+ }
+
+ public void setNext(Interceptor next) {
+ throw new IllegalStateException("This interceptor must be the last one in an target interceptor chain");
+ }
+
+ public Interceptor getNext() {
+ return null;
+ }
+
+ public boolean isOptimizable() {
+ return true;
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java
new file mode 100644
index 0000000000..aec281d190
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.core.wire;
+
+import org.apache.tuscany.spi.wire.ProxyCreationException;
+
+/**
+ * Thrown when an {@link org.apache.tuscany.spi.model.Operation} cannot be mapped to a method on an interface
+ * @version $Rev$ $Date$
+ */
+public class NoMethodForOperationException extends ProxyCreationException {
+ public NoMethodForOperationException() {
+ }
+
+ public NoMethodForOperationException(String message) {
+ super(message);
+ }
+
+ public NoMethodForOperationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public NoMethodForOperationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingInterceptor.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingInterceptor.java
new file mode 100644
index 0000000000..b5e1be42d5
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingInterceptor.java
@@ -0,0 +1,172 @@
+/*
+ * 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.core.wire;
+
+import java.net.URI;
+import java.util.LinkedList;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.services.work.WorkScheduler;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * Adds non-blocking behavior to an invocation chain
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class NonBlockingInterceptor implements Interceptor {
+
+ private static final Message RESPONSE = new ImmutableMessage();
+
+ private WorkScheduler workScheduler;
+ private WorkContext workContext;
+ private Interceptor next;
+
+ public NonBlockingInterceptor(WorkScheduler workScheduler, WorkContext workContext) {
+ this.workScheduler = workScheduler;
+ this.workContext = workContext;
+ }
+
+ public NonBlockingInterceptor(WorkScheduler workScheduler, WorkContext workContext, Interceptor next) {
+ this.workScheduler = workScheduler;
+ this.workContext = workContext;
+ this.next = next;
+ }
+
+ public Message invoke(final Message msg) {
+ // Retrieve conversation id to transfer to new thread
+ // Notice that we cannot clear the conversation id from the current thread
+ final Object conversationID = workContext.getIdentifier(Scope.CONVERSATION);
+ // Schedule the invocation of the next interceptor in a new Work instance
+ try {
+ workScheduler.scheduleWork(new Runnable() {
+ public void run() {
+ workContext.setCorrelationId(null);
+ // if we got a conversation id, transfer it to new thread
+ if (conversationID != null) {
+ workContext.setIdentifier(Scope.CONVERSATION, conversationID);
+ }
+ next.invoke(msg);
+ }
+ });
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ return RESPONSE;
+ }
+
+ public Interceptor getNext() {
+ return next;
+ }
+
+ public void setNext(Interceptor next) {
+ this.next = next;
+ }
+
+ public boolean isOptimizable() {
+ return false;
+ }
+
+ /**
+ * A dummy message passed back on an invocation
+ */
+ private static class ImmutableMessage implements Message {
+
+ public Object getBody() {
+ return null;
+ }
+
+ public void setBody(Object body) {
+ if (body != null) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public void setTargetInvoker(TargetInvoker invoker) {
+ throw new UnsupportedOperationException();
+ }
+
+ public TargetInvoker getTargetInvoker() {
+ return null;
+ }
+
+ public Message getRelatedCallbackMessage() {
+ return null;
+ }
+
+ public URI getFromAddress() {
+ return null;
+ }
+
+ public void setFromAddress(URI fromAddress) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void pushCallbackUri(URI fromAddress) {
+ throw new UnsupportedOperationException();
+ }
+
+ public LinkedList<URI> getCallbackUris() {
+ return null;
+ }
+
+ public void setCallbackUris(LinkedList<URI> uris) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getMessageId() {
+ return null;
+ }
+
+ public void setMessageId(Object messageId) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getCorrelationId() {
+ return null;
+ }
+
+ public void setCorrelationId(Object correlationId) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isFault() {
+ return false;
+ }
+
+ public void setBodyWithFault(Object fault) {
+ throw new UnsupportedOperationException();
+ }
+
+ public short getConversationSequence() {
+ return TargetInvoker.NONE;
+ }
+
+ public void setConversationSequence(short sequence) {
+
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java
new file mode 100644
index 0000000000..49c73e2808
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.core.wire;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * Returns a target instance directly from a wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class OptimizedWireObjectFactory<B> implements ObjectFactory<B> {
+ private final Class<B> type;
+ private Wire wire;
+
+ public OptimizedWireObjectFactory(Class<B> type, Wire factory) {
+ this.wire = factory;
+ this.type = type;
+ }
+
+ public B getInstance() throws ObjectCreationException {
+ try {
+ return type.cast(wire.getTargetInstance());
+ } catch (TargetResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/ProxyServiceExtension.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/ProxyServiceExtension.java
new file mode 100644
index 0000000000..7c8cf0db3a
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/ProxyServiceExtension.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.core.wire;
+
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.IncompatibleServiceContractException;
+import org.apache.tuscany.spi.wire.ProxyService;
+
+/**
+ * Base class for wire service extensions
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class ProxyServiceExtension implements ProxyService {
+ protected WorkContext context;
+
+ protected ProxyServiceExtension(WorkContext context) {
+ this.context = context;
+ }
+
+ public boolean checkCompatibility(ServiceContract<?> source,
+ ServiceContract<?> target,
+ boolean ignoreCallback,
+ boolean silent)
+ throws IncompatibleServiceContractException {
+ if (source == target) {
+ // Shortcut for performance
+ return true;
+ }
+ if (source.isRemotable() != target.isRemotable()) {
+ if (!silent) {
+ throw new IncompatibleServiceContractException("Remotable settings do not match", source, target);
+ } else {
+ return false;
+ }
+ }
+ if (source.isConversational() != target.isConversational()) {
+ if (!silent) {
+ throw new IncompatibleServiceContractException("Interaction scopes do not match", source, target);
+ } else {
+ return false;
+ }
+ }
+
+ for (Operation<?> operation : source.getOperations().values()) {
+ Operation<?> targetOperation = target.getOperations().get(operation.getName());
+ if (targetOperation == null) {
+ if (!silent) {
+ throw new IncompatibleServiceContractException("Operation not found on target", source, target);
+ } else {
+ return false;
+ }
+ }
+ if (!operation.equals(targetOperation)) {
+ if (!silent) {
+ throw new IncompatibleServiceContractException("Target operations are not compatible", source,
+ target);
+ } else {
+ return false;
+ }
+ }
+ }
+
+ if (ignoreCallback) {
+ return true;
+ }
+
+ for (Operation<?> operation : source.getCallbackOperations().values()) {
+ Operation<?> targetOperation = target.getCallbackOperations().get(operation.getName());
+ if (targetOperation == null) {
+ if (!silent) {
+ throw new IncompatibleServiceContractException("Callback operation not found on target",
+ source,
+ target,
+ null,
+ targetOperation);
+ } else {
+ return false;
+ }
+ }
+ if (!operation.equals(targetOperation)) {
+ if (!silent) {
+ throw new IncompatibleServiceContractException("Target callback operation is not compatible",
+ source,
+ target,
+ operation,
+ targetOperation);
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireImpl.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireImpl.java
new file mode 100644
index 0000000000..0518ce5132
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireImpl.java
@@ -0,0 +1,137 @@
+/*
+ * 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.core.wire;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * Default implementation of a Wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class WireImpl implements Wire {
+ private URI sourceUri;
+ private URI targetUri;
+ private QName bindingType;
+ private ServiceContract sourceContract;
+ private ServiceContract targetContract;
+ private boolean optimizable;
+ private Map<Operation<?>, InvocationChain> chains = new HashMap<Operation<?>, InvocationChain>();
+ private Map<Operation<?>, InvocationChain> callbackChains = new HashMap<Operation<?>, InvocationChain>();
+ private AtomicComponent target;
+
+ /**
+ * Creates a wire with a local binding
+ */
+ public WireImpl() {
+ }
+
+ /**
+ * Creates a wire with the given binding type
+ *
+ * @param bindingType the binding type
+ */
+ public WireImpl(QName bindingType) {
+ this.bindingType = bindingType;
+ }
+
+ public URI getSourceUri() {
+ return sourceUri;
+ }
+
+ public void setSourceUri(URI sourceUri) {
+ this.sourceUri = sourceUri;
+ }
+
+ public URI getTargetUri() {
+ return targetUri;
+ }
+
+ public void setTargetUri(URI targetUri) {
+ this.targetUri = targetUri;
+ }
+
+ public QName getBindingType() {
+ return bindingType;
+ }
+
+
+ public ServiceContract getSourceContract() {
+ return sourceContract;
+ }
+
+ public void setSourceContract(ServiceContract contract) {
+ this.sourceContract = contract;
+ }
+
+
+ public ServiceContract getTargetContract() {
+ return targetContract;
+ }
+
+ public void setTargetContract(ServiceContract contract) {
+ this.targetContract = contract;
+ }
+
+ public boolean isOptimizable() {
+ return optimizable;
+ }
+
+ public void setOptimizable(boolean optimizable) {
+ this.optimizable = optimizable;
+ }
+
+ public Object getTargetInstance() throws TargetResolutionException {
+ if (target == null) {
+ return null;
+ }
+ return target.getTargetInstance();
+ }
+
+ public void setTarget(AtomicComponent target) {
+ this.target = target;
+ }
+
+ public Map<Operation<?>, InvocationChain> getInvocationChains() {
+ return Collections.unmodifiableMap(chains);
+ }
+
+ public void addInvocationChain(Operation<?> operation, InvocationChain chain) {
+ chains.put(operation, chain);
+ }
+
+ public Map<Operation<?>, InvocationChain> getCallbackInvocationChains() {
+ return Collections.unmodifiableMap(callbackChains);
+ }
+
+ public void addCallbackInvocationChain(Operation<?> operation, InvocationChain chain) {
+ callbackChains.put(operation, chain);
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java
new file mode 100644
index 0000000000..bb46d53e84
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java
@@ -0,0 +1,84 @@
+/*
+ * 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.core.wire;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.wire.ChainHolder;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.ProxyService;
+
+/**
+ * Uses a wire to return an object instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class WireObjectFactory<T> implements ObjectFactory<T> {
+ private Class<T> interfaze;
+ private Wire wire;
+ private ProxyService proxyService;
+ // the cache of proxy interface method to operation mappings
+ private Map<Method, ChainHolder> mappings;
+ private boolean optimizable;
+
+ /**
+ * Constructor.
+ *
+ * @param interfaze the interface to inject on the client
+ * @param wire the backing wire
+ * @param proxyService the wire service to create the proxy
+ * @throws NoMethodForOperationException
+ */
+ public WireObjectFactory(Class<T> interfaze, Wire wire, ProxyService proxyService)
+ throws NoMethodForOperationException {
+ this.interfaze = interfaze;
+ this.wire = wire;
+ this.proxyService = proxyService;
+ this.mappings = WireUtils.createInterfaceToWireMapping(interfaze, wire);
+ if (wire.isOptimizable()
+ && wire.getSourceContract().getInterfaceClass() != null
+ && interfaze.isAssignableFrom(wire.getSourceContract().getInterfaceClass())) {
+ optimizable = true;
+ }
+ }
+
+ public T getInstance() throws ObjectCreationException {
+ if (optimizable) {
+ try {
+ return interfaze.cast(wire.getTargetInstance());
+ } catch (TargetResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+ } else {
+ // clone the cached mappings
+ Map<Method, ChainHolder> newChains = new HashMap<Method, ChainHolder>(mappings.size());
+ for (Map.Entry<Method, ChainHolder> entry : mappings.entrySet()) {
+ newChains.put(entry.getKey(), entry.getValue().clone());
+ }
+ return interfaze.cast(proxyService.createProxy(interfaze, wire, newChains));
+ }
+ }
+
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java
new file mode 100644
index 0000000000..b3e9c8177e
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.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.core.wire;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.ChainHolder;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.Wire;
+
+/**
+ * Utilities for operating on wires
+ *
+ * @version $Rev$ $Date$
+ */
+public final class WireUtils {
+
+ private WireUtils() {
+ }
+
+ /**
+ * Maps invocation chains on a wire to corresponding methods
+ *
+ * @param wire the wire containing the invocation chains to map
+ * @param methods the methods to map to
+ * @return a collection containing the method to invocation chain mapping
+ * @throws NoMethodForOperationException
+ */
+ public static Map<Method, InvocationChain> createInboundMapping(Wire wire, Method[] methods)
+ throws NoMethodForOperationException {
+ Map<Method, InvocationChain> chains = new HashMap<Method, InvocationChain>();
+ for (Map.Entry<Operation<?>, InvocationChain> entry : wire.getInvocationChains().entrySet()) {
+ Operation<?> operation = entry.getKey();
+ InvocationChain chain = entry.getValue();
+ Method method = findMethod(operation, methods);
+ if (method == null) {
+ throw new NoMethodForOperationException(operation.getName());
+ }
+ chains.put(method, chain);
+ }
+ return chains;
+ }
+
+
+ /**
+ * Maps methods on an interface to operations on a wire
+ *
+ * @param interfaze the interface to map from
+ * @param wire the wire to map to
+ * @return a collection of method to operation mappings
+ * @throws NoMethodForOperationException
+ */
+ public static Map<Method, ChainHolder> createInterfaceToWireMapping(Class<?> interfaze, Wire wire)
+ throws NoMethodForOperationException {
+ Map<Operation<?>, InvocationChain> invocationChains = wire.getInvocationChains();
+ Map<Method, ChainHolder> chains = new HashMap<Method, ChainHolder>(invocationChains.size());
+ Method[] methods = interfaze.getMethods();
+ for (Map.Entry<Operation<?>, InvocationChain> entry : invocationChains.entrySet()) {
+ Operation operation = entry.getKey();
+ Method method = findMethod(operation, methods);
+ if (method == null) {
+ throw new NoMethodForOperationException(operation.getName());
+ }
+ chains.put(method, new ChainHolder(entry.getValue()));
+ }
+ return chains;
+ }
+
+ /**
+ * Determines if the given wire is optimizable, i.e. its invocation chains may be bypassed during an invocation.
+ * This is typically calculated during the connect phase to optimize away invocation chains.
+ *
+ * @param wire the wire
+ * @return true if the wire is optimizable
+ */
+ public static boolean isOptimizable(Wire wire) {
+ for (InvocationChain chain : wire.getInvocationChains().values()) {
+ if (chain.getHeadInterceptor() != null) {
+ Interceptor current = chain.getHeadInterceptor();
+ if (current == null) {
+ break;
+ }
+ while (current != null) {
+ if (!current.isOptimizable()) {
+ return false;
+ }
+ current = current.getNext();
+ }
+ }
+ }
+ // if there is a callback, the wire is never optimizable since the callback target needs to be disambiguated
+ return wire.getCallbackInvocationChains().isEmpty();
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java
new file mode 100644
index 0000000000..9c67c17977
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java
@@ -0,0 +1,155 @@
+/*
+ * 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.core.wire.jdk;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.osoa.sca.NoRegisteredCallbackException;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ReactivationException;
+import org.apache.tuscany.spi.component.SCAExternalizable;
+import org.apache.tuscany.spi.component.WorkContext;
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findOperation;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.AbstractInvocationHandler;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WireInvocationHandler;
+
+
+/**
+ * Responsible for dispatching to a callback through a wire.
+ * <p/>
+ * TODO cache target invoker
+ *
+ * @version $Rev$ $Date$
+ */
+public class JDKCallbackInvocationHandler extends AbstractInvocationHandler
+ implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable {
+ private transient WorkContext context;
+ private transient Map<URI, Wire> wires;
+ private List<String> sourceWireNames;
+
+ /**
+ * Constructor used for deserialization only
+ */
+ public JDKCallbackInvocationHandler() {
+ sourceWireNames = new ArrayList<String>();
+ wires = new HashMap<URI, Wire>();
+ }
+
+ public JDKCallbackInvocationHandler(List<Wire> wireList, WorkContext context) {
+ this.context = context;
+ this.wires = new HashMap<URI, Wire>();
+ for (Wire wire : wireList) {
+ wires.put(wire.getSourceUri(), wire);
+ }
+ sourceWireNames = new ArrayList<String>();
+ for (URI uri : wires.keySet()) {
+ sourceWireNames.add(uri.getFragment());
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) {
+ return "[Proxy - " + Integer.toHexString(hashCode()) + "]";
+ } else if (method.getDeclaringClass().equals(Object.class)
+ && "equals".equals(method.getName())) {
+ // TODO implement
+ throw new UnsupportedOperationException();
+ } else if (Object.class.equals(method.getDeclaringClass())
+ && "hashCode".equals(method.getName())) {
+ return hashCode();
+ // TODO beter hash algorithm
+ }
+ LinkedList<URI> callbackUris = context.getCallbackUris();
+ assert callbackUris != null;
+ URI targetAddress = callbackUris.getLast();
+ assert targetAddress != null;
+ Wire wire = wires.get(targetAddress);
+ assert wire != null;
+ Map<Operation<?>, InvocationChain> chains = wire.getCallbackInvocationChains();
+ Operation operation = findOperation(method, chains.keySet());
+ InvocationChain chain = chains.get(operation);
+ TargetInvoker invoker = chain.getTargetInvoker();
+ Object correlationId = context.getCorrelationId();
+ context.setCorrelationId(null);
+ try {
+ return invoke(chain, invoker, args, correlationId, callbackUris);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof NoRegisteredCallbackException) {
+ throw t;
+ }
+ throw e;
+ }
+ }
+
+
+ public Object invoke(Method method, Object[] args) throws Throwable {
+ return invoke(null, method, args);
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ int i = sourceWireNames.size() - 1;
+ out.writeInt(i);
+ for (String name : sourceWireNames) {
+ out.writeObject(name);
+ }
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ int num = in.readInt();
+ for (int i = 0; i <= num; i++) {
+ sourceWireNames.add((String) in.readObject());
+ }
+ }
+
+ public void setWorkContext(WorkContext context) {
+ this.context = context;
+ }
+
+ public void reactivate() throws ReactivationException {
+ AtomicComponent owner = context.getCurrentAtomicComponent();
+ if (owner == null) {
+ throw new ReactivationException("Current atomic component not set on work context");
+ }
+ for (String name : sourceWireNames) {
+ // TODO JFM support multiplicity, remove get(0)
+ Wire wire = owner.getWires(name).get(0);
+ wires.put(wire.getSourceUri(), wire);
+
+ }
+ }
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInvocationHandler.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInvocationHandler.java
new file mode 100644
index 0000000000..8ca53a74db
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInvocationHandler.java
@@ -0,0 +1,263 @@
+/*
+ * 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.core.wire.jdk;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ReactivationException;
+import org.apache.tuscany.spi.component.SCAExternalizable;
+import org.apache.tuscany.spi.component.TargetInvocationException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.AbstractInvocationHandler;
+import org.apache.tuscany.spi.wire.ChainHolder;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WireInvocationHandler;
+
+import org.apache.tuscany.core.wire.NoMethodForOperationException;
+import org.apache.tuscany.core.wire.WireUtils;
+
+
+/**
+ * Dispatches to a target through a wire.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class JDKInvocationHandler extends AbstractInvocationHandler
+ implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable {
+ private static final long serialVersionUID = -6155278451964527325L;
+
+ // the wire this handler fronts
+ private transient Wire wire;
+ // the name of the source reference the wire is attached to, used during deserialization
+ private String referenceName;
+ // the interface the reference proxy implements
+ private Class<?> proxyInterface;
+ private transient WorkContext workContext;
+ // if the associated wire has a callback
+ private transient boolean callback;
+ // if the associated wire is conversational
+ private transient boolean conversational;
+ /*
+ * an association of an operation to chain holder. The holder contains an invocation chain
+ * and a local clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the
+ * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers
+ * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker
+ * is not cacheable, the master associated with the wire chains will be used.
+ */
+ private transient Map<Method, ChainHolder> chains;
+
+ /**
+ * Constructor used for deserialization only
+ */
+ public JDKInvocationHandler() {
+ }
+
+ public JDKInvocationHandler(Class<?> interfaze, Wire wire, WorkContext workContext)
+ throws NoMethodForOperationException {
+ this.workContext = workContext;
+ this.proxyInterface = interfaze;
+ this.wire = wire;
+ init(interfaze, wire, null);
+ }
+
+ public JDKInvocationHandler(Class<?> interfaze,
+ Wire wire,
+ Map<Method, ChainHolder> mapping,
+ WorkContext workContext)
+ throws NoMethodForOperationException {
+ this.workContext = workContext;
+ this.proxyInterface = interfaze;
+ init(interfaze, wire, mapping);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ ChainHolder holder = chains.get(method);
+ if (holder == null) {
+ if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) {
+ return "[Proxy - " + Integer.toHexString(hashCode()) + "]";
+ } else if (method.getDeclaringClass().equals(Object.class)
+ && "equals".equals(method.getName())) {
+ // TODO implement
+ throw new UnsupportedOperationException();
+ } else if (Object.class.equals(method.getDeclaringClass())
+ && "hashCode".equals(method.getName())) {
+ return hashCode();
+ // TODO beter hash algorithm
+ }
+ throw new TargetInvocationException("Operation not configured", method.getName());
+ }
+ TargetInvoker invoker = getInvoker(holder);
+ InvocationChain chain = holder.getChain();
+
+// JFM commonting out temporarily
+// if (wireContainerIsAtomicComponent && contractHasCallback && !callbackIsImplemented) {
+// throw new NoRegisteredCallbackException("Instance is does not implement callback: "
+// + callbackClassName);
+// }
+
+ if (conversational) {
+ Object id = workContext.getIdentifier(Scope.CONVERSATION);
+ if (id == null) {
+ String convIdFromThread = createConversationID();
+ workContext.setIdentifier(Scope.CONVERSATION, convIdFromThread);
+ }
+ }
+ LinkedList<URI> list = null;
+ if (callback) {
+ // set up callback address
+ list = workContext.getCallbackUris();
+ if (list == null) {
+ list = new LinkedList<URI>();
+ workContext.setCallbackUris(list);
+ }
+ list.add(wire.getSourceUri());
+ }
+ // send the invocation down the wire
+ Object result = invoke(chain, invoker, args, null, list);
+
+ if (callback) {
+ list = workContext.getCallbackUris();
+ if (list != null) {
+ // pop last address
+ list.removeLast();
+ }
+ }
+ return result;
+ }
+
+ public Object invoke(Method method, Object[] args) throws Throwable {
+ return invoke(null, method, args);
+ }
+
+ public void setWorkContext(WorkContext context) {
+ workContext = context;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(referenceName);
+ out.writeObject(proxyInterface);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ referenceName = (String) in.readObject();
+ proxyInterface = (Class<?>) in.readObject();
+ }
+
+ public void reactivate() throws ReactivationException {
+ AtomicComponent owner = workContext.getCurrentAtomicComponent();
+ if (owner == null) {
+ throw new ReactivationException("Current atomic component not set on work context");
+ }
+ List<Wire> wires = owner.getWires(referenceName);
+ if (wires == null) {
+ throw new ReactivationException("Reference wire not found", referenceName, owner.getUri().toString());
+ }
+ // TODO handle multiplicity
+ Wire wire = wires.get(0);
+ try {
+ init(proxyInterface, wire, null);
+ } catch (NoMethodForOperationException e) {
+ throw new ReactivationException(e);
+ }
+ }
+
+ /**
+ * Reinitializes the proxy handler
+ *
+ * @param interfaze the interface the proxy implements
+ * @param wire the wire fronted by the proxy
+ * @param mapping a mapping from proxy interface methods to invocation chain holders
+ * @throws NoMethodForOperationException
+ */
+ private void init(Class<?> interfaze, Wire wire, Map<Method, ChainHolder> mapping)
+ throws NoMethodForOperationException {
+ ServiceContract contract = wire.getSourceContract();
+ this.referenceName = wire.getSourceUri().getFragment();
+ this.conversational = contract.isConversational();
+ this.callback = contract.getCallbackClass() != null;
+ // FIXME JFM this should not be dependent on PojoAtomicComponent
+ // JFM commenting out as this should not be specific to pojo types
+// this.wireContainerIsAtomicComponent = scaObject instanceof PojoAtomicComponent;
+// if (wireContainerIsAtomicComponent && contractHasCallback) {
+// this.callbackIsImplemented =
+// ((PojoAtomicComponent) scaObject).implementsCallback(contract.getCallbackClass());
+// } else {
+// this.callbackIsImplemented = false;
+// }
+ if (mapping == null) {
+ chains = WireUtils.createInterfaceToWireMapping(interfaze, wire);
+ } else {
+ chains = mapping;
+ }
+ }
+
+ /**
+ * Returns the cached or a new target invoker to associate with the invocation
+ *
+ * @param holder the chain holder
+ * @return the target invoker
+ * @throws TargetInvocationException
+ * @throws CloneNotSupportedException
+ */
+ private TargetInvoker getInvoker(ChainHolder holder) throws TargetInvocationException, CloneNotSupportedException {
+ InvocationChain chain = holder.getChain();
+ if (holder.getCachedInvoker() == null) {
+ assert chain != null;
+ if (chain.getTargetInvoker() == null) {
+ String name = chain.getOperation().getName();
+ throw new TargetInvocationException("No target invoker configured for operation", name);
+ }
+ if (chain.getTargetInvoker().isCacheable()) {
+ // clone and store the invoker locally
+ holder.setCachedInvoker((TargetInvoker) chain.getTargetInvoker().clone());
+ return holder.getCachedInvoker();
+ } else {
+ return chain.getTargetInvoker();
+ }
+ } else {
+ assert chain != null;
+ return chain.getTargetInvoker();
+ }
+ }
+
+ /**
+ * Creates a new conversational id
+ *
+ * @return the conversational id
+ */
+ private String createConversationID() {
+ return UUID.randomUUID().toString();
+ }
+
+}
diff --git a/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKProxyService.java b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKProxyService.java
new file mode 100644
index 0000000000..ef3f30edb9
--- /dev/null
+++ b/sca-java-1.x/tags/kernel/2.0-alpha-incubating/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKProxyService.java
@@ -0,0 +1,92 @@
+/*
+ * 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.core.wire.jdk;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.Map;
+
+import org.osoa.sca.CallableReference;
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.EagerInit;
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.wire.ChainHolder;
+import org.apache.tuscany.spi.wire.ProxyCreationException;
+import org.apache.tuscany.spi.wire.Wire;
+
+import org.apache.tuscany.core.wire.ProxyServiceExtension;
+
+/**
+ * the default implementation of a wire service that uses JDK dynamic proxies
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+@EagerInit
+public class JDKProxyService extends ProxyServiceExtension {
+
+ public JDKProxyService() {
+ super(null);
+ }
+
+ @Constructor
+ public JDKProxyService(@Reference WorkContext context) {
+ super(context);
+ }
+
+ public <T> T createProxy(Class<T> interfaze, Wire wire) throws ProxyCreationException {
+ assert interfaze != null;
+ assert wire != null;
+ JDKInvocationHandler handler = new JDKInvocationHandler(interfaze, wire, context);
+ ClassLoader cl = interfaze.getClassLoader();
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ }
+
+ public <T> T createProxy(Class<T> interfaze, Wire wire, Map<Method, ChainHolder> mapping)
+ throws ProxyCreationException {
+ assert interfaze != null;
+ assert wire != null;
+ assert mapping != null;
+ JDKInvocationHandler handler = new JDKInvocationHandler(interfaze, wire, context);
+ ClassLoader cl = interfaze.getClassLoader();
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ }
+
+ public Object createCallbackProxy(Class<?> interfaze, List<Wire> wires) throws ProxyCreationException {
+ ClassLoader cl = interfaze.getClassLoader();
+ JDKCallbackInvocationHandler handler = new JDKCallbackInvocationHandler(wires, context);
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ }
+
+ public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException {
+ InvocationHandler handler = Proxy.getInvocationHandler(target);
+ if (handler instanceof JDKInvocationHandler) {
+ // TODO return a ServiceReference
+ throw new UnsupportedOperationException();
+ } else if (handler instanceof JDKCallbackInvocationHandler) {
+ // TODO return a CallbackReference
+ throw new UnsupportedOperationException();
+ } else {
+ throw new IllegalArgumentException("Not a Tuscany SCA proxy");
+ }
+ }
+}