summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core')
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java77
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java56
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java70
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java74
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java61
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java73
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java88
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java262
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java83
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java241
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java609
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java54
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java93
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java41
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java36
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java42
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java58
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java57
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java72
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java35
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java211
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java33
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java47
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java46
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java31
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java31
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java45
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java28
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java158
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java189
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java50
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java217
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java58
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java135
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java54
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java41
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java63
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java126
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java47
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java63
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java75
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java54
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java130
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java121
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java80
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java157
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java67
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java357
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java217
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java171
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java201
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java244
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java190
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java66
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java61
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java83
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java73
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java56
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java79
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java1415
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java65
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java63
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java67
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java62
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.java49
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java66
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java59
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java65
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java60
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.java62
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java65
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java58
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java244
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java67
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java60
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java256
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java806
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java57
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java60
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java59
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java55
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java56
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java62
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java73
-rwxr-xr-xsca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java33
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java61
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java60
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java145
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java65
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java118
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java162
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java135
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java282
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java232
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java71
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java151
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java120
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java33
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java50
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java114
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java67
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java235
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java126
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedCompositeContext.java80
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java49
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java90
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java98
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java67
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java161
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java100
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java198
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java90
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java63
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java144
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java51
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java41
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java106
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java124
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java142
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java62
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java38
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java59
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java546
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java36
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java37
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java410
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java62
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java45
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java41
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java33
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java57
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java36
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java78
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java150
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java115
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java64
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java156
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java32
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java184
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java101
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java70
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java75
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java57
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java51
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java54
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java47
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java50
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java32
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java36
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java57
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java35
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java33
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java50
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java50
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java29
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java48
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java119
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java26
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java34
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java146
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java39
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java60
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java49
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java250
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java96
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java315
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java89
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java88
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java111
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java52
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java50
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java181
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java196
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java103
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java98
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java118
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java159
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java191
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java112
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java54
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java64
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java321
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java78
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java58
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java167
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java79
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java297
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java65
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java197
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java96
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java63
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java311
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java100
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java83
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java90
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java32
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java132
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java122
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java142
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java198
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java206
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java217
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java73
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java166
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java220
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java93
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java439
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java29
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java60
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java41
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java166
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java95
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java107
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java59
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java33
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java42
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java189
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java47
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java53
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java176
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java55
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java84
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java287
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java146
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java137
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java173
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java249
-rw-r--r--sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java114
266 files changed, 28028 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java
new file mode 100644
index 0000000000..7727759a88
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+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(OutboundInvocationChain 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java
new file mode 100644
index 0000000000..1841af679e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.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.binding.local;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.BoundReferenceDefinition;
+import org.apache.tuscany.spi.model.BoundServiceDefinition;
+
+/**
+ * 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(CompositeComponent parent,
+ BoundServiceDefinition boundServiceDefinition,
+ LocalBindingDefinition bindingDefinition,
+ DeploymentContext deploymentContext)
+ throws BuilderException {
+ return new LocalServiceBinding(boundServiceDefinition.getName(), parent);
+ }
+
+
+ public ReferenceBinding build(CompositeComponent parent,
+ BoundReferenceDefinition boundReferenceDefinition,
+ LocalBindingDefinition bindingDefinition,
+ DeploymentContext deploymentContext) throws BuilderException {
+ return new LocalReferenceBinding(boundReferenceDefinition.getName(), parent);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java
new file mode 100644
index 0000000000..777beeb00e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return Wire.LOCAL_BINDING;
+ }
+
+ public LocalBindingDefinition load(CompositeComponent parent,
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java
new file mode 100644
index 0000000000..03f42ca99c
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.InboundWire;
+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.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * Dispatches a callback invocation to the callback instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalCallbackTargetInvoker extends AbstractLocalTargetInvoker {
+ private Operation operation;
+ private InboundWire inboundWire;
+
+ public LocalCallbackTargetInvoker(Operation operation, InboundWire inboundWire) {
+ assert operation != null : "Operation method cannot be null";
+ this.operation = operation;
+ this.inboundWire = inboundWire;
+ }
+
+ 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 {
+ Object targetAddress = msg.popFromAddress();
+ if (targetAddress == null) {
+ throw new AssertionError("Popped a null from address from message");
+ }
+ //TODO optimize as this is slow in local invocations
+ Map<Operation<?>, OutboundInvocationChain> sourceCallbackInvocationChains =
+ inboundWire.getSourceCallbackInvocationChains(targetAddress);
+ OutboundInvocationChain chain = sourceCallbackInvocationChains.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java
new file mode 100644
index 0000000000..9117fe903e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.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.binding.local;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.CoreRuntimeException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.model.ServiceContract;
+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(String name, CompositeComponent parent) throws CoreRuntimeException {
+ super(name, parent);
+ }
+
+ public QName getBindingType() {
+ return Wire.LOCAL_BINDING;
+ }
+
+ public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation)
+ throws TargetInvokerCreationException {
+ if (operation.isCallback()) {
+ return new LocalCallbackTargetInvoker(operation, inboundWire);
+ } else {
+ return new LocalTargetInvoker(operation, outboundWire);
+ }
+ }
+
+ public TargetInvoker createCallbackTargetInvoker(ServiceContract contract, Operation operation)
+ throws TargetInvokerCreationException {
+ return new LocalCallbackTargetInvoker(operation, inboundWire);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java
new file mode 100644
index 0000000000..6205172d7b
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.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 javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.CoreRuntimeException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.model.ServiceContract;
+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(String name, CompositeComponent parent) throws CoreRuntimeException {
+ super(name, parent);
+ }
+
+ public QName getBindingType() {
+ return Wire.LOCAL_BINDING;
+ }
+
+ public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation)
+ throws TargetInvokerCreationException {
+ if (operation.isCallback()) {
+ return new LocalCallbackTargetInvoker(operation, getInboundWire());
+ } else {
+ return new LocalTargetInvoker(operation, outboundWire);
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java
new file mode 100644
index 0000000000..5b564c93b8
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.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.binding.local;
+
+import org.apache.tuscany.spi.model.Operation;
+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.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * Dispatches an invocation through a composite service or reference using the local binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocalTargetInvoker extends AbstractLocalTargetInvoker {
+ private OutboundInvocationChain chain;
+ private Object fromAddress;
+ private boolean contractHasCallback;
+
+ public LocalTargetInvoker(Operation operation, OutboundWire outboundWire) {
+ assert operation != null;
+ chain = outboundWire.getInvocationChains().get(operation);
+ assert chain != null;
+ fromAddress = (outboundWire.getContainer() == null) ? null : outboundWire.getContainer().getName();
+ contractHasCallback = outboundWire.getServiceContract().getCallbackClass() != null;
+ }
+
+ @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) {
+ msg.pushFromAddress(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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java
new file mode 100644
index 0000000000..0f6b4a2c92
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.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.bootstrap;
+
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.spi.bootstrap.RuntimeComponent;
+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;
+
+/**
+ * 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 the RuntimeComponent that forms the fundamental root of the component assembly. This component has two
+ * children: a {@link org.apache.tuscany.spi.component.CompositeComponent} that is the root for all system
+ * components, and a {@link org.apache.tuscany.spi.component.CompositeComponent} that is the root for all
+ * application components.
+ *
+ * @return a new RuntimeComponent; basically a new Tuscany instance
+ */
+ RuntimeComponent createRuntime();
+
+ /**
+ * 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 createConnector();
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java
new file mode 100644
index 0000000000..762568eb01
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.bootstrap.ComponentNames;
+import org.apache.tuscany.spi.bootstrap.RuntimeComponent;
+import org.apache.tuscany.spi.builder.Builder;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.spi.services.management.TuscanyManagementService;
+
+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.builder.ConnectorImpl;
+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.CompositeComponentImpl;
+import org.apache.tuscany.core.implementation.composite.CompositeLoader;
+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.composite.SystemCompositeBuilder;
+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.wire.jdk.JDKWireService;
+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 TuscanyManagementService managementService;
+
+ /**
+ * 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 managementService management service used by the runtime.
+ */
+ public DefaultBootstrapper(MonitorFactory monitorFactory,
+ XMLInputFactory xmlFactory,
+ TuscanyManagementService managementService) {
+ this.monitorFactory = monitorFactory;
+ this.xmlFactory = xmlFactory;
+ this.managementService = managementService;
+ }
+
+ /**
+ * Returns the MonitorFactory being used by this bootstrapper.
+ *
+ * @return the MonitorFactory being used by this bootstrapper
+ */
+ public MonitorFactory getMonitorFactory() {
+ return monitorFactory;
+ }
+
+ /**
+ * Create the RuntimeComponent that will form the root of the component tree. Returns an new instance of a {@link
+ * DefaultRuntime} with the system and application root components initialized with default composite components.
+ *
+ * @return a newly created root for the component tree
+ */
+ public RuntimeComponent createRuntime() {
+ DefaultRuntime runtime = new DefaultRuntime();
+ CompositeComponent systemComponent =
+ new CompositeComponentImpl(ComponentNames.TUSCANY_SYSTEM_ROOT, runtime, null, true);
+ runtime.setSystemComponent(systemComponent);
+ CompositeComponent rootComponent =
+ new CompositeComponentImpl(ComponentNames.TUSCANY_APPLICATION_ROOT, runtime, null, null);
+ runtime.setRootComponent(rootComponent);
+ return runtime;
+ }
+
+ /**
+ * 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);
+ 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 createConnector() {
+ return new ConnectorImpl();
+ }
+
+ /**
+ * 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, new JDKWireService());
+ SystemCompositeBuilder builder =
+ new SystemCompositeBuilder(builderRegistry, createConnector(), managementService);
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java
new file mode 100644
index 0000000000..978d10fc37
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.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.bootstrap;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+
+import org.apache.tuscany.spi.bootstrap.ComponentNames;
+import org.apache.tuscany.spi.bootstrap.RuntimeComponent;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.wire.InboundWire;
+
+import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl;
+
+/**
+ * The default implementation of the Tuscany runtime component
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultRuntime extends CompositeComponentImpl implements RuntimeComponent {
+ private CompositeComponent rootComponent;
+ private CompositeComponent systemComponent;
+
+ /**
+ * Initialize a default runtime with an empty set of Property values.
+ */
+ public DefaultRuntime() {
+ this(new HashMap<String, Document>());
+ }
+
+ /**
+ * Initialize a runtime with the a set of properties
+ *
+ * @param runtimeProperties Property values for the runtime itself
+ */
+ public DefaultRuntime(Map<String, Document> runtimeProperties) {
+ super(ComponentNames.TUSCANY_RUNTIME, null, null, runtimeProperties);
+ }
+
+ protected void setRootComponent(CompositeComponent rootComponent) {
+ this.rootComponent = rootComponent;
+ }
+
+ protected void setSystemComponent(CompositeComponent systemComponent) {
+ this.systemComponent = systemComponent;
+ }
+
+ public CompositeComponent getRootComponent() {
+ return rootComponent;
+ }
+
+ public CompositeComponent getSystemComponent() {
+ return systemComponent;
+ }
+
+ public Deployer getDeployer() throws TargetResolutionException {
+ InboundWire wire = systemComponent.resolveExternalAutowire(Deployer.class);
+ if (wire != null) {
+ return (Deployer) wire.getTargetService();
+ }
+ return null;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java
new file mode 100644
index 0000000000..3a1501c98d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.QualifiedName;
+import org.apache.tuscany.spi.annotation.Autowire;
+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.MissingWireTargetException;
+import org.apache.tuscany.spi.builder.ScopeNotFoundException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.BoundReferenceDefinition;
+import org.apache.tuscany.spi.model.BoundServiceDefinition;
+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.InteractionScope;
+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.spi.wire.WireService;
+
+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 {
+ protected WireService wireService;
+ protected 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(@Autowire
+ ScopeRegistry scopeRegistry, @Autowire
+ WireService wireService) {
+ this.scopeRegistry = scopeRegistry;
+ this.wireService = wireService;
+ }
+
+ 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(CompositeComponent parent,
+ ComponentDefinition<I> componentDefinition,
+ DeploymentContext context) throws BuilderException {
+ Class<?> implClass = componentDefinition.getImplementation().getClass();
+ // noinspection SuspiciousMethodCalls
+ ComponentBuilder<I> componentBuilder = (ComponentBuilder<I>) componentBuilders.get(implClass);
+ try {
+ if (componentBuilder == null) {
+ String name = implClass.getName();
+ throw new NoRegisteredBuilderException("No builder registered for implementation", name);
+ }
+
+ Component component = componentBuilder.build(parent, componentDefinition, context);
+ if (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()) {
+ InteractionScope intScope = serviceDef.getServiceContract().getInteractionScope();
+ if (intScope == InteractionScope.CONVERSATIONAL) {
+ hasConversationalContract = true;
+ break;
+ }
+ }
+ if (!hasConversationalContract) {
+ Map<String, ReferenceDefinition> references = componentType.getReferences();
+ for (ReferenceDefinition refDef : references.values()) {
+ // TODO check for a conversational callback contract
+ // refDef.getServiceContract() ...
+ }
+ }
+ 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);
+ }
+ }
+ ComponentType<?, ?, ?> componentType = componentDefinition.getImplementation().getComponentType();
+ assert componentType != null : "Component type must be set";
+ // create wires for the component
+ if (wireService != null && component instanceof AtomicComponent) {
+ wireService.createWires((AtomicComponent) component, componentDefinition);
+ }
+ return component;
+ } catch (BuilderException e) {
+ e.addContextName(componentDefinition.getName());
+ throw e;
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public Service build(CompositeComponent parent,
+ BoundServiceDefinition boundServiceDefinition,
+ DeploymentContext deploymentContext) throws BuilderException {
+ String name = boundServiceDefinition.getName();
+ ServiceContract<?> serviceContract = boundServiceDefinition.getServiceContract();
+ if (boundServiceDefinition.getBindings().isEmpty()) {
+ // if no bindings are configured, default to the local binding.
+ // this should be changed to allow runtime selection
+ if (boundServiceDefinition.getBindings().isEmpty()) {
+ // TODO JFM implement capability for the runtime to choose a binding
+ boundServiceDefinition.addBinding(new LocalBindingDefinition());
+ }
+ }
+ boolean system = parent.isSystem();
+ URI targetUri = boundServiceDefinition.getTarget();
+ Service service = new ServiceImpl(name, parent, serviceContract, targetUri, system);
+ for (BindingDefinition definition : boundServiceDefinition.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(parent, boundServiceDefinition, definition, deploymentContext);
+ if (wireService != null) {
+ URI uri = boundServiceDefinition.getTarget();
+ if (uri == null) {
+ throw new MissingWireTargetException("Service uri not specified");
+ }
+ String path = uri.getPath();
+ ServiceContract<?> contract = boundServiceDefinition.getServiceContract();
+ wireService.createWires(binding, contract, path);
+ }
+ service.addServiceBinding(binding);
+ }
+ return service;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Reference build(CompositeComponent parent,
+ BoundReferenceDefinition referenceDefinition,
+ DeploymentContext context) throws BuilderException {
+ String name = referenceDefinition.getName();
+ 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(name, parent, contract);
+ for (BindingDefinition bindingDefinition : referenceDefinition.getBindings()) {
+ Class<?> bindingClass = bindingDefinition.getClass();
+ // noinspection SuspiciousMethodCalls
+ BindingBuilder bindingBuilder = bindingBuilders.get(bindingClass);
+ ReferenceBinding binding = bindingBuilder.build(parent, referenceDefinition, bindingDefinition, context);
+ // create wires for the component
+ if (wireService != null) {
+ URI targetUri = bindingDefinition.getTargetUri();
+ // it is possible for a binding to not have a URI
+ QualifiedName targetName = null;
+ if (targetUri != null) {
+ targetName = new QualifiedName(targetUri.getPath());
+ }
+ wireService.createWires(binding, contract, targetName);
+
+ }
+ reference.addReferenceBinding(binding);
+
+ }
+ return reference;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java
new file mode 100644
index 0000000000..1fb5c9f0f5
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java
@@ -0,0 +1,609 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.List;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.builder.MissingWireTargetException;
+import org.apache.tuscany.spi.builder.WiringException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.SCAObject;
+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.TargetResolutionException;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.idl.java.JavaServiceContract;
+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.services.work.WorkScheduler;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.IncompatibleServiceContractException;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.WirePostProcessorRegistry;
+import org.apache.tuscany.spi.wire.WireService;
+
+import org.apache.tuscany.core.wire.LoopBackWire;
+import org.apache.tuscany.core.wire.NonBlockingBridgingInterceptor;
+import org.apache.tuscany.core.wire.SynchronousBridgingInterceptor;
+import org.apache.tuscany.core.wire.WireUtils;
+
+/**
+ * The default connector implmentation
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class ConnectorImpl implements Connector {
+ private WirePostProcessorRegistry postProcessorRegistry;
+ private WireService wireService;
+ private WorkContext workContext;
+ private WorkScheduler scheduler;
+
+ public ConnectorImpl() {
+ }
+
+ @Constructor
+ public ConnectorImpl(@Autowire WireService wireService,
+ @Autowire WirePostProcessorRegistry processorRegistry,
+ @Autowire WorkScheduler scheduler,
+ @Autowire WorkContext workContext) {
+ this.postProcessorRegistry = processorRegistry;
+ this.wireService = wireService;
+ this.scheduler = scheduler;
+ this.workContext = workContext;
+ }
+
+ public void connect(SCAObject source) throws WiringException {
+ if (source instanceof Component) {
+ handleComponent((Component) source);
+ } else if (source instanceof Reference) {
+ handleReference((Reference) source);
+ } else if (source instanceof Service) {
+ handleService((Service) source);
+ } else {
+ throw new AssertionError("Invalid source type");
+ }
+ }
+
+ public void connect(InboundWire sourceWire, OutboundWire targetWire, boolean optimizable)
+ throws WiringException {
+ Map<Operation<?>, OutboundInvocationChain> targetChains = targetWire.getInvocationChains();
+ if (sourceWire.getContainer() != null && sourceWire.getContainer().isSystem()) {
+ sourceWire.setTargetWire(targetWire);
+ // system services do not need to have their chains processed, return
+ return;
+ }
+ for (InboundInvocationChain inboundChain : sourceWire.getInvocationChains().values()) {
+ // match invocation chains
+ OutboundInvocationChain outboundChain = targetChains.get(inboundChain.getOperation());
+ if (outboundChain == null) {
+ throw new IncompatibleInterfacesException(sourceWire, targetWire);
+ }
+ connect(inboundChain, outboundChain);
+ }
+ if (postProcessorRegistry != null) {
+ // run wire post-processors
+ postProcessorRegistry.process(sourceWire, targetWire);
+ }
+ if (optimizable && WireUtils.isOptimizable(sourceWire) && WireUtils.isOptimizable(targetWire)) {
+ sourceWire.setOptimizable(true);
+ sourceWire.setTargetWire(targetWire);
+ }
+ }
+
+ /**
+ * Connects the source outbound wire to a corresponding target inbound wire
+ *
+ * @param sourceWire the source wire to connect
+ * @param targetWire the target wire to connect to
+ * @param optimizable true if the wire connection can be optimized
+ * @throws WiringException
+ */
+ public void connect(OutboundWire sourceWire, InboundWire targetWire, boolean optimizable)
+ throws WiringException {
+ SCAObject source = sourceWire.getContainer();
+ assert source != null;
+ SCAObject target = targetWire.getContainer();
+ assert target != null;
+ Map<Operation<?>, InboundInvocationChain> targetChains = targetWire.getInvocationChains();
+ if (sourceWire.getContainer() != null && sourceWire.getContainer().isSystem()) {
+ sourceWire.setTargetWire(targetWire);
+ // system services do not need to have their chains processed, return
+ return;
+ }
+ // match outbound to inbound chains
+ for (OutboundInvocationChain outboundChain : sourceWire.getInvocationChains().values()) {
+ Operation<?> operation = outboundChain.getOperation();
+ InboundInvocationChain inboundChain = targetChains.get(operation);
+ if (inboundChain == null) {
+ throw new IncompatibleInterfacesException(sourceWire, targetWire);
+ }
+ Operation<?> inboundOperation = inboundChain.getOperation();
+ boolean isOneWayOperation = operation.isNonBlocking();
+ TargetInvoker invoker;
+ if (target instanceof Component) {
+ Component component = (Component) target;
+ QualifiedName wireTargetName = sourceWire.getTargetName();
+ String portName = null;
+ if (wireTargetName != null) {
+ portName = wireTargetName.getPortName();
+ }
+ try {
+ invoker = component.createTargetInvoker(portName, inboundOperation, targetWire);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireConnectException("Error connecting source and target", sourceWire, targetWire, e);
+ }
+ } else if (target instanceof ReferenceBinding) {
+ ReferenceBinding referenceBinding = (ReferenceBinding) target;
+ try {
+ invoker = referenceBinding.createTargetInvoker(targetWire.getServiceContract(), inboundOperation);
+ } catch (TargetInvokerCreationException e) {
+ String targetName = targetWire.getContainer().getName();
+ throw new WireConnectException("Error processing inbound wire", null, null, targetName, null, e);
+ }
+ } else if (target instanceof ServiceBinding) {
+ ServiceBinding binding = (ServiceBinding) target;
+ try {
+ invoker = binding.createTargetInvoker(targetWire.getServiceContract(), inboundChain.getOperation());
+ } catch (TargetInvokerCreationException e) {
+ String targetName = targetWire.getContainer().getName();
+ throw new WireConnectException("Error processing inbound wire", null, null, targetName, null, e);
+ }
+ } else {
+ throw new AssertionError();
+ }
+
+ if (source instanceof ServiceBinding) {
+ // services are a special case: invoker must go on the inbound and outbound chains
+ if (target instanceof Component && isOneWayOperation) {
+ // if the target is a component and the operation is non-blocking
+ connect(outboundChain, inboundChain, invoker, true);
+ } else {
+ connect(outboundChain, inboundChain, invoker, false);
+ }
+ ServiceBinding binding = (ServiceBinding) source;
+ InboundInvocationChain chain = binding.getInboundWire().getInvocationChains().get(operation);
+ chain.setTargetInvoker(invoker);
+ } else {
+ if (target instanceof Component && isOneWayOperation) {
+ // if the target is a component and the operation is non-blocking
+ connect(outboundChain, inboundChain, invoker, true);
+ } else {
+ connect(outboundChain, inboundChain, invoker, false);
+ }
+ }
+ }
+
+ // create source callback chains and connect them if target callback chains exist
+ Map<Operation<?>, OutboundInvocationChain> sourceCallbackChains =
+ targetWire.getSourceCallbackInvocationChains(source.getName());
+ for (InboundInvocationChain inboundChain : sourceWire.getTargetCallbackInvocationChains().values()) {
+ Operation<?> operation = inboundChain.getOperation();
+ if (sourceCallbackChains != null && sourceCallbackChains.get(operation) != null) {
+ String opName = operation.getName();
+ throw new IllegalCallbackException("Source callback chain should not exist for operation",
+ opName,
+ sourceWire,
+ targetWire);
+ }
+
+ ServiceContract<?> targetContract = targetWire.getServiceContract();
+ assert targetContract != null;
+ String opName = operation.getName();
+ assert opName != null;
+ Operation targetOp = targetContract.getCallbackOperations().get(opName);
+ OutboundInvocationChain outboundChain = wireService.createOutboundChain(targetOp);
+ targetWire.addSourceCallbackInvocationChain(source.getName(), targetOp, outboundChain);
+ if (source instanceof Component) {
+ Component component = (Component) source;
+ TargetInvoker invoker;
+ try {
+ invoker = component.createTargetInvoker(targetOp.getName(), operation, null);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireConnectException("Error connecting source and target", sourceWire, targetWire, e);
+ }
+ boolean isOneWayOperation = targetOp.isNonBlocking();
+ if (target instanceof Component && isOneWayOperation) {
+ // if the target is a component and the operation is non-blocking
+ connect(outboundChain, inboundChain, invoker, true);
+ } else {
+ connect(outboundChain, inboundChain, invoker, false);
+ }
+ } else if (source instanceof ReferenceBinding) {
+ ReferenceBinding binding = (ReferenceBinding) source;
+ ServiceContract sourceContract = sourceWire.getServiceContract();
+ TargetInvoker invoker;
+ try {
+ invoker = binding.createTargetInvoker(sourceContract, operation);
+ } catch (TargetInvokerCreationException e) {
+ throw new WireConnectException("Error connecting source and target", sourceWire, targetWire, e);
+ }
+ connect(outboundChain, inboundChain, invoker, false);
+ } else if (source instanceof ServiceBinding) {
+ ServiceBinding binding = (ServiceBinding) source;
+ ServiceContract sourceContract = sourceWire.getServiceContract();
+ TargetInvoker invoker;
+ try {
+ invoker = binding.createTargetInvoker(sourceContract, operation);
+ } catch (TargetInvokerCreationException e) {
+ String targetName = sourceWire.getContainer().getName();
+ throw new WireConnectException("Error processing callback wire", null, null, targetName, null, e);
+ }
+ connect(outboundChain, inboundChain, invoker, false);
+ } else {
+ throw new AssertionError();
+ }
+ }
+ if (postProcessorRegistry != null) {
+ // run wire post-processors
+ postProcessorRegistry.process(sourceWire, targetWire);
+ }
+ // perform optimization, if possible
+ if (optimizable && WireUtils.isOptimizable(sourceWire) && WireUtils.isOptimizable(targetWire)) {
+ sourceWire.setOptimizable(true);
+ sourceWire.setTargetWire(targetWire);
+ }
+ }
+
+ /**
+ * Connects a source to target chain
+ *
+ * @param sourceChain the source chain
+ * @param targetChain the target chain
+ * @param invoker the invoker to place on the source chain for dispatching invocations
+ * @param nonBlocking true if the operation is non-blocking
+ */
+ protected void connect(OutboundInvocationChain sourceChain,
+ InboundInvocationChain targetChain,
+ TargetInvoker invoker,
+ boolean nonBlocking) throws WireConnectException {
+ Interceptor head = targetChain.getHeadInterceptor();
+ if (head == null) {
+ throw new WireConnectException("Inbound chain must contain at least one interceptor");
+ }
+ if (nonBlocking) {
+ sourceChain.setTargetInterceptor(new NonBlockingBridgingInterceptor(scheduler, workContext, head));
+ } else {
+ sourceChain.setTargetInterceptor(new SynchronousBridgingInterceptor(head));
+ }
+ sourceChain.prepare();
+ sourceChain.setTargetInvoker(invoker);
+ }
+
+
+ /**
+ * Connects an inbound source chain to an outbound target chain
+ *
+ * @param sourceChain the source chain to connect
+ * @param targetChain the target chain to connect
+ */
+ protected void connect(InboundInvocationChain sourceChain, OutboundInvocationChain targetChain)
+ throws WireConnectException {
+ Interceptor head = targetChain.getHeadInterceptor();
+ if (head == null) {
+ throw new WireConnectException("Outbound chain must contain at least one interceptor");
+ }
+ // invocations from inbound to outbound chains are always synchronous as they occur in services and references
+ sourceChain.addInterceptor(new SynchronousBridgingInterceptor(head));
+ }
+
+ /**
+ * Connects an outbound wire to its target in a composite.
+ *
+ * @param sourceWire the source wire to connect
+ * @throws WiringException
+ */
+ protected void connect(SCAObject source, OutboundWire sourceWire, SCAObject target) throws WiringException {
+ assert sourceWire.getTargetName() != null;
+ QualifiedName targetName = sourceWire.getTargetName();
+ if (target instanceof Component) {
+ connect(source, sourceWire, (Component) target);
+ } else if (target instanceof Reference) {
+ connect(source, sourceWire, (Reference) target);
+ } else if (target instanceof Service) {
+ connect(source, sourceWire, (Service) target);
+ } else if (target == null) {
+ String sourceName = sourceWire.getContainer().getName();
+ String sourceReference = sourceWire.getReferenceName();
+ throw new TargetServiceNotFoundException("Target service not found",
+ sourceName,
+ sourceReference,
+ targetName.getPartName(),
+ targetName.getPortName());
+ } else {
+ String sourceName = sourceWire.getContainer().getName();
+ String sourceRef = sourceWire.getReferenceName();
+ String partName = targetName.getPartName();
+ String portName = targetName.getPortName();
+ throw new InvalidTargetTypeException("Invalid target type", sourceName, sourceRef, partName, portName);
+ }
+ }
+
+ protected void connect(SCAObject source, OutboundWire sourceWire, Reference target) throws WiringException {
+ assert sourceWire.getTargetName() != null;
+ QualifiedName targetName = sourceWire.getTargetName();
+ InboundWire targetWire = null;
+ for (ReferenceBinding binding : target.getReferenceBindings()) {
+ InboundWire candidate = binding.getInboundWire();
+ if (sourceWire.getBindingType().equals(candidate.getBindingType())) {
+ targetWire = candidate;
+ break;
+ }
+ }
+ if (targetWire == null) {
+ if (target.getReferenceBindings().size() > 0 && source instanceof Component) {
+ // TODO create a pluggable algorithm for selecting the binding type
+ targetWire = target.getReferenceBindings().get(0).getInboundWire();
+ }
+ if (targetWire == null) {
+ throw new NoCompatibleBindingsException(source.getName(),
+ targetName.getPartName(),
+ targetName.getPortName());
+ }
+ }
+ checkIfWireable(sourceWire, targetWire);
+ boolean optimizable = isOptimizable(source.getScope(), target.getScope());
+ connect(sourceWire, targetWire, optimizable);
+ }
+
+ protected void connect(SCAObject source, OutboundWire sourceWire, Service target) throws WiringException {
+ assert sourceWire.getTargetName() != null;
+ QualifiedName targetName = sourceWire.getTargetName();
+ InboundWire targetWire = null;
+ for (ServiceBinding binding : target.getServiceBindings()) {
+ InboundWire candidate = binding.getInboundWire();
+ if (sourceWire.getBindingType().equals(candidate.getBindingType())) {
+ targetWire = candidate;
+ break;
+ }
+ }
+ if (targetWire == null) {
+ throw new NoCompatibleBindingsException(source.getName(),
+ targetName.getPartName(),
+ targetName.getPortName());
+ }
+ checkIfWireable(sourceWire, targetWire);
+ boolean optimizable = isOptimizable(source.getScope(), target.getScope());
+ connect(sourceWire, targetWire, optimizable);
+ }
+
+ protected void connect(SCAObject source, OutboundWire sourceWire, Component target)
+ throws WiringException {
+ assert sourceWire.getTargetName() != null;
+ QualifiedName targetName = sourceWire.getTargetName();
+ InboundWire targetWire;
+ // FIXME JFM should we move getInboundSystemWire up to Component?
+ if (target instanceof CompositeComponent && source.isSystem()) {
+ targetWire = ((CompositeComponent) target).getInboundSystemWire(targetName.getPortName());
+ } else {
+ targetWire = target.getInboundWire(targetName.getPortName());
+ }
+ if (targetWire == null) {
+ String sourceName = sourceWire.getContainer().getName();
+ String sourceReference = sourceWire.getReferenceName();
+ throw new TargetServiceNotFoundException("Target service does not exist or is not configured with a "
+ + "local binding",
+ sourceName,
+ sourceReference,
+ targetName.getPartName(),
+ targetName.getPortName());
+ }
+ checkIfWireable(sourceWire, targetWire);
+ boolean optimizable = isOptimizable(source.getScope(), target.getScope());
+ connect(sourceWire, targetWire, optimizable);
+ }
+
+ protected void autowire(OutboundWire outboundWire, CompositeComponent parent)
+ throws WiringException {
+ // JFM FIXME test coverage for this method
+ InboundWire targetWire;
+ try {
+ Class interfaze = outboundWire.getServiceContract().getInterfaceClass();
+ if (CompositeComponent.class.equals(interfaze)) {
+ JavaServiceContract contract = new JavaServiceContract(CompositeComponent.class);
+ targetWire = new LoopBackWire();
+ targetWire.setServiceContract(contract);
+ targetWire.setContainer(parent);
+ outboundWire.setTargetWire(targetWire);
+ return;
+ }
+ if (outboundWire.getContainer().isSystem()) {
+ targetWire = parent.resolveSystemAutowire(interfaze);
+ } else {
+ targetWire = parent.resolveAutowire(interfaze);
+ }
+ } catch (TargetResolutionException e) {
+ String sourceReference = outboundWire.getReferenceName();
+ String sourceName = outboundWire.getContainer().getName();
+ throw new WireConnectException("Error resolving autowire target",
+ sourceName,
+ sourceReference,
+ null,
+ null,
+ e);
+ }
+ if (targetWire == null) {
+ // autowire may return null if it is optional. The client must decide if an error should be thrown
+ return;
+ }
+ Scope sourceScope = outboundWire.getContainer().getScope();
+ Scope targetScope = targetWire.getContainer().getScope();
+ boolean optimizable = isOptimizable(sourceScope, targetScope);
+ connect(outboundWire, targetWire, optimizable);
+ }
+
+ protected void checkIfWireable(OutboundWire sourceWire, InboundWire targetWire)
+ throws IncompatibleInterfacesException {
+ if (wireService == null) {
+ Class<?> sourceInterface = sourceWire.getServiceContract().getInterfaceClass();
+ Class<?> targetInterface = targetWire.getServiceContract().getInterfaceClass();
+ if (!sourceInterface.isAssignableFrom(targetInterface)) {
+ throw new IncompatibleInterfacesException(sourceWire, targetWire);
+ }
+ } else {
+ try {
+ ServiceContract sourceContract = sourceWire.getServiceContract();
+ ServiceContract targetContract = targetWire.getServiceContract();
+ wireService.checkCompatibility(sourceContract, targetContract, false);
+ } catch (IncompatibleServiceContractException e) {
+ throw new IncompatibleInterfacesException(sourceWire, targetWire, e);
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+ /**
+ * Connects wires from a service to a target
+ *
+ * @param service the service
+ * @throws WiringException if an exception connecting the service wires is encountered
+ */
+ private void handleService(Service service) throws WiringException {
+ CompositeComponent parent = service.getParent();
+ assert parent != null;
+ for (ServiceBinding binding : service.getServiceBindings()) {
+ InboundWire inboundWire = binding.getInboundWire();
+ OutboundWire outboundWire = binding.getOutboundWire();
+ // For a composite reference only, since its outbound wire comes from its parent composite,
+ // the corresponding target would not lie in its parent but rather in its parent's parent
+ SCAObject target;
+ if (service.isSystem()) {
+ target = parent.getSystemChild(outboundWire.getTargetName().getPartName());
+ } else {
+ target = parent.getChild(outboundWire.getTargetName().getPartName());
+ }
+ // connect the outbound service wire to the target
+ connect(binding, outboundWire, target);
+ // NB: this connect must be done after the outbound service chain is connected to its target above
+ connect(inboundWire, outboundWire, true);
+ }
+ }
+
+ private void handleReference(Reference reference) throws WiringException {
+ CompositeComponent parent = reference.getParent();
+ assert parent != null;
+ for (ReferenceBinding binding : reference.getReferenceBindings()) {
+ InboundWire inboundWire = binding.getInboundWire();
+ Map<Operation<?>, InboundInvocationChain> inboundChains = inboundWire.getInvocationChains();
+ for (InboundInvocationChain chain : inboundChains.values()) {
+ // add target invoker on inbound side
+ ServiceContract contract = inboundWire.getServiceContract();
+ Operation operation = chain.getOperation();
+ TargetInvoker invoker;
+ try {
+ invoker = binding.createTargetInvoker(contract, operation);
+ } catch (TargetInvokerCreationException e) {
+ String targetName = inboundWire.getContainer().getName();
+ throw new WireConnectException("Error processing inbound wire",
+ null,
+ null,
+ targetName,
+ null,
+ e);
+ }
+ chain.setTargetInvoker(invoker);
+ chain.prepare();
+ }
+ OutboundWire outboundWire = binding.getOutboundWire();
+ // connect the reference's inbound and outbound wires
+ connect(inboundWire, outboundWire, true);
+ }
+ }
+
+ private void handleComponent(Component component) throws WiringException {
+ CompositeComponent parent = component.getParent();
+ assert parent != null;
+ // connect outbound wires for component references to their targets
+ for (List<OutboundWire> referenceWires : component.getOutboundWires().values()) {
+ for (OutboundWire outboundWire : referenceWires) {
+ try {
+ if (component.isSystem()) {
+ if (outboundWire.isAutowire()) {
+ autowire(outboundWire, parent);
+
+ } else {
+ SCAObject target = parent.getSystemChild(outboundWire.getTargetName().getPartName());
+ connect(component, outboundWire, target);
+ }
+ } else {
+ if (outboundWire.isAutowire()) {
+ autowire(outboundWire, parent);
+ } else {
+ if (outboundWire.getTargetName() == null) {
+ String referenceName = outboundWire.getReferenceName();
+ throw new MissingWireTargetException("Target name was null", referenceName);
+ }
+ SCAObject target = parent.getChild(outboundWire.getTargetName().getPartName());
+ connect(component, outboundWire, target);
+ }
+ }
+ } catch (WiringException e) {
+ e.addContextName(component.getName());
+ e.addContextName(parent.getName());
+ throw e;
+ }
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java
new file mode 100644
index 0000000000..5ca843e198
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.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.builder;
+
+import org.apache.tuscany.spi.builder.WiringException;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * Denotes an illegal callback
+ *
+ * @version $Rev$ $Date$
+ */
+public class IllegalCallbackException extends WiringException {
+
+ public IllegalCallbackException(String message,
+ String identifier,
+ String sourceName,
+ String referenceName,
+ String targetName,
+ String serviceName) {
+ super(message, identifier);
+ setSourceName(sourceName);
+ setReferenceName(referenceName);
+ setTargetName(targetName);
+ setTargetServiceName(serviceName);
+ }
+
+
+ public IllegalCallbackException(String message, String identifier, OutboundWire source, InboundWire target) {
+ super(message, identifier);
+ setSourceName(source.getContainer().getName());
+ setReferenceName(source.getReferenceName());
+ setTargetName(target.getContainer().getName());
+ setTargetServiceName(target.getServiceName());
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java
new file mode 100644
index 0000000000..4b94983c34
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.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.builder;
+
+import org.apache.tuscany.spi.builder.WiringException;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * Denotes an attempt to wire incompatible interfaces
+ *
+ * @version $Rev$ $Date$
+ */
+public class IncompatibleInterfacesException extends WiringException {
+
+
+ public IncompatibleInterfacesException(String message,
+ String sourceName,
+ String referenceName,
+ String targetName,
+ String targetServiceName) {
+ super(message);
+ setSourceName(sourceName);
+ setReferenceName(referenceName);
+ setTargetName(targetName);
+ setTargetServiceName(targetServiceName);
+ }
+
+ public IncompatibleInterfacesException(String message, String sourceName,
+ String referenceName,
+ String targetName,
+ String serviceName,
+ Throwable cause) {
+ super(message, cause);
+ setSourceName(sourceName);
+ setReferenceName(referenceName);
+ setTargetName(targetName);
+ setTargetServiceName(serviceName);
+ }
+
+ public IncompatibleInterfacesException(InboundWire source, OutboundWire target) {
+ super("Incompatible source and target interfaces");
+ setTargetServiceName(source.getServiceName());
+ if (source.getContainer() != null) {
+ setSourceName(source.getContainer().getName());
+ }
+ setReferenceName(target.getReferenceName());
+ if (target.getContainer() != null) {
+ setTargetName(target.getContainer().getName());
+ }
+ }
+
+ public IncompatibleInterfacesException(OutboundWire source, InboundWire target) {
+ super("Incompatible source and target interfaces");
+ setTargetServiceName(target.getServiceName());
+ if (source.getContainer() != null) {
+ setSourceName(source.getContainer().getName());
+ }
+ setReferenceName(source.getReferenceName());
+ if (target.getContainer() != null) {
+ setTargetName(target.getContainer().getName());
+ }
+ }
+
+ public IncompatibleInterfacesException(OutboundWire source, InboundWire target, Throwable throwable) {
+ super("Incompatible source and target interfaces", throwable);
+ setTargetServiceName(target.getServiceName());
+ if (source.getContainer() != null) {
+ setSourceName(source.getContainer().getName());
+ }
+ setReferenceName(source.getReferenceName());
+ if (target.getContainer() != null) {
+ setTargetName(target.getContainer().getName());
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java
new file mode 100644
index 0000000000..e96fb764a0
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.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.builder;
+
+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,
+ String sourceName,
+ String referenceName,
+ String targetName,
+ String serviceName) {
+ super(message);
+ setSourceName(sourceName);
+ setReferenceName(referenceName);
+ setTargetName(targetName);
+ setTargetServiceName(serviceName);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java
new file mode 100644
index 0000000000..620fbf6694
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.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 org.apache.tuscany.spi.builder.WiringException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class NoCompatibleBindingsException extends WiringException {
+ public NoCompatibleBindingsException(String sourceName,
+ String targetName,
+ String serviceName) {
+ super("No compatible bindings for source and target");
+ setSourceName(sourceName);
+ setTargetName(targetName);
+ setTargetServiceName(serviceName);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java
new file mode 100644
index 0000000000..873bf619b0
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.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.builder;
+
+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,
+ String sourceName,
+ String referenceName,
+ String targetName,
+ String serviceName) {
+ super(message);
+ setSourceName(sourceName);
+ setReferenceName(referenceName);
+ setTargetName(targetName);
+ setTargetServiceName(serviceName);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java
new file mode 100644
index 0000000000..89105d27b4
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.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.builder;
+
+import org.apache.tuscany.spi.builder.WiringException;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * Denotes a general error connecting two wires
+ *
+ * @version $Rev$ $Date$
+ */
+public class WireConnectException extends WiringException {
+
+ public WireConnectException(String message) {
+ super(message);
+ }
+
+ public WireConnectException(String message,
+ String sourceName,
+ String referenceName,
+ String targetName,
+ String serviceName,
+ Throwable throwable) {
+ super(message, throwable);
+ setSourceName(sourceName);
+ setReferenceName(referenceName);
+ setTargetName(targetName);
+ setTargetServiceName(serviceName);
+ }
+
+
+ public WireConnectException(String message, OutboundWire source, InboundWire target, Throwable throwable) {
+ super(message, throwable);
+ setSourceName(source.getContainer().getName());
+ setReferenceName(source.getReferenceName());
+ setTargetName(target.getContainer().getName());
+ setTargetServiceName(target.getServiceName());
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java
new file mode 100644
index 0000000000..3bc617066a
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.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.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.wire.WirePostProcessor;
+import org.apache.tuscany.spi.wire.WirePostProcessorRegistry;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * 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(OutboundWire source, InboundWire target) {
+ for (WirePostProcessor processor : processors) {
+ processor.process(source, target);
+ }
+ }
+
+ public void process(InboundWire source, OutboundWire target) {
+ for (WirePostProcessor processor : processors) {
+ processor.process(source, target);
+ }
+ }
+
+ public void register(WirePostProcessor processor) {
+ processors.add(processor);
+ }
+
+ public void unregister(WirePostProcessor processor) {
+ processors.remove(processor);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java
new file mode 100644
index 0000000000..16cf27048a
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.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.builder;
+
+import java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire 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.getSourceName() != null && e.getReferenceName() != null) {
+ writer.write("\nSource : " + e.getSourceName() + "/" + e.getReferenceName());
+ } else if (e.getSourceName() != null) {
+ writer.write("\nSource : " + e.getSourceName());
+ }
+ if (e.getTargetName() != null && e.getTargetServiceName() != null) {
+ writer.write("\nTarget : " + e.getTargetName() + "/" + e.getTargetServiceName());
+ } else if (e.getTargetName() != null) {
+ writer.write("\nTarget : " + e.getTargetName());
+ }
+ e.appendContextStack(writer).append("\n");
+ return writer;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java
new file mode 100644
index 0000000000..8d2afc35d9
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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.CompositeComponent;
+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_ROUTING_CHAIN = 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 getCurrentCorrelationId() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return map.get(CORRELATION_ID);
+ }
+
+ public void setCurrentCorrelationId(Object correlationId) {
+ Map<Object, Object> map = getWorkContextMap();
+ map.put(CORRELATION_ID, correlationId);
+ }
+
+ 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<Object> getCurrentCallbackRoutingChain() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return (LinkedList<Object>) map.get(CALLBACK_ROUTING_CHAIN);
+ }
+
+ public void setCurrentCallbackRoutingChain(LinkedList<Object> callbackRoutingChain) {
+ Map<Object, Object> map = getWorkContextMap();
+ map.put(CALLBACK_ROUTING_CHAIN, callbackRoutingChain);
+ }
+
+ public CompositeComponent getRemoteComponent() {
+ Map<Object, Object> map = workContext.get();
+ if (map == null) {
+ return null;
+ }
+ return (CompositeComponent) map.get(REMOTE_CONTEXT);
+ }
+
+
+ public void setRemoteComponent(CompositeComponent 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java
new file mode 100644
index 0000000000..ce058404da
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.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.event;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.event.Event;
+
+/**
+ * Implemented by runtime events associated with a composite, e.g. lifecycle events
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public interface CompositeEvent extends Event {
+
+ CompositeComponent getComposite();
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java
new file mode 100644
index 0000000000..fba36feaf6
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.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 org.apache.tuscany.spi.component.CompositeComponent;
+
+/**
+ * Propagated when a composite starts
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class CompositeStart extends AbstractEvent implements CompositeEvent {
+
+ private CompositeComponent component;
+
+ /**
+ * Creates a composite stop event
+ *
+ * @param source the source of the event
+ * @param component the composite component associated the composite being stopped
+ */
+ public CompositeStart(Object source, CompositeComponent component) {
+ super(source);
+ this.component = component;
+ }
+
+ public CompositeComponent getComposite() {
+ return component;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java
new file mode 100644
index 0000000000..6b3e37f619
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.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 org.apache.tuscany.spi.component.CompositeComponent;
+
+/**
+ * Propagated when a composite stops
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class CompositeStop extends AbstractEvent implements CompositeEvent {
+
+ private CompositeComponent component;
+
+ /**
+ * Creates a composite stop event
+ *
+ * @param source the source of the event
+ * @param component the composite component associated the composite being stopped
+ */
+ public CompositeStop(Object source, CompositeComponent component) {
+ super(source);
+ this.component = component;
+ }
+
+ public CompositeComponent getComposite() {
+ return component;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java
new file mode 100644
index 0000000000..cde61eaa5a
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.getName());
+ }
+
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java
new file mode 100644
index 0000000000..21ff792282
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.CompositeStart;
+import org.apache.tuscany.core.component.event.CompositeStop;
+
+/**
+ * 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 CompositeStart) {
+ try {
+ eagerInitComponents();
+ } catch (ObjectCreationException e) {
+ monitor.eagerInitializationError(e);
+ } catch (TargetResolutionException e) {
+ monitor.eagerInitializationError(e);
+ }
+ lifecycleState = RUNNING;
+ } else if (event instanceof CompositeStop) {
+ 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) {
+ try {
+ ctx = new InstanceWrapperImpl(component, component.createInstance());
+ } catch (ObjectCreationException e) {
+ e.addContextName(component.getName());
+ throw e;
+ }
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java
new file mode 100644
index 0000000000..a761f05d4b
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java
new file mode 100644
index 0000000000..1a77f3ecb3
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.getName());
+ }
+ } 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java
new file mode 100644
index 0000000000..32dfaed8d9
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire ScopeRegistry registry,
+ @Autowire WorkContext context,
+ @Autowire 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java
new file mode 100644
index 0000000000..14713f9144
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire ScopeRegistry registry,
+ @Autowire 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java
new file mode 100644
index 0000000000..50f4a31128
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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 {
+
+ Object getInstance();
+
+ boolean isStarted();
+
+ void start() throws TargetInitializationException;
+
+ void stop() throws TargetDestructionException;
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java
new file mode 100644
index 0000000000..c4648d1e7b
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.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 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 implements InstanceWrapper {
+ private Object instance;
+ private AtomicComponent component;
+ private boolean started;
+
+ public InstanceWrapperImpl(AtomicComponent component, Object instance) {
+ assert component != null;
+ assert instance != null;
+ this.component = component;
+ this.instance = instance;
+ }
+
+ public boolean isStarted() {
+ return started;
+ }
+
+ public Object getInstance() {
+ if (!started) {
+ throw new IllegalStateException("Instance not started");
+ }
+ return instance;
+ }
+
+ public void start() throws TargetInitializationException {
+ component.init(instance);
+ started = true;
+ }
+
+ public void stop() throws TargetDestructionException {
+ component.destroy(instance);
+ started = false;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java
new file mode 100644
index 0000000000..0377bcd548
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.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.scope;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java
new file mode 100644
index 0000000000..8e05510723
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire ScopeRegistry registry,
+ @Autowire 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java
new file mode 100644
index 0000000000..dcc772d01c
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.component.CompositeComponent;
+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 CompositeComponent compositeComponent;
+
+ 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;
+ this.compositeComponent = sourceWire.getContainer().getParent();
+ }
+
+ /**
+ * @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>();
+ metadata.put(CompositeComponent.class, compositeComponent);
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java
new file mode 100644
index 0000000000..046578ae66
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java
new file mode 100644
index 0000000000..4fe7a4efa7
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.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.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osoa.sca.annotations.EagerInit;
+
+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;
+ for (DataBinding binding : bindings.values()) {
+ dataType = binding.introspect(javaType);
+ if (dataType != null) {
+ return dataType;
+ }
+ }
+ return null;
+ }
+
+ public DataType introspectType(Object value) {
+ DataType dataType;
+ for (DataBinding binding : bindings.values()) {
+ dataType = binding.introspect(value);
+ if (dataType != null) {
+ return dataType;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java
new file mode 100644
index 0000000000..e687a161eb
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.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.databinding.impl;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.databinding.Mediator;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.WirePostProcessorExtension;
+import org.osoa.sca.annotations.Constructor;
+
+/**
+ * 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(@Autowire Mediator mediator) {
+ super();
+ this.mediator = mediator;
+ }
+
+ public void process(OutboundWire source, InboundWire target) {
+ Map<Operation<?>, OutboundInvocationChain> chains = source.getInvocationChains();
+ for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : chains.entrySet()) {
+ Operation<?> sourceOperation = entry.getKey();
+ Operation<?> targetOperation =
+ getTargetOperation(target.getInvocationChains().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(source, sourceOperation, targetOperation);
+ interceptor.setMediator(mediator);
+ entry.getValue().addInterceptor(0, interceptor);
+ }
+ }
+
+ // Check if there's a callback
+ Map callbackOperations = source.getServiceContract().getCallbackOperations();
+ if (callbackOperations == null || callbackOperations.isEmpty()) {
+ return;
+ }
+ Object targetAddress = source.getContainer().getName();
+ Map<Operation<?>, OutboundInvocationChain> callbackChains =
+ target.getSourceCallbackInvocationChains(targetAddress);
+ if (callbackChains == null) {
+ // callback chains could be null
+ return;
+ }
+ for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : callbackChains.entrySet()) {
+ Operation<?> sourceOperation = entry.getKey();
+ Operation<?> targetOperation =
+ getTargetOperation(source.getTargetCallbackInvocationChains().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(source, sourceOperation, targetOperation);
+ interceptor.setMediator(mediator);
+ entry.getValue().addInterceptor(0, interceptor);
+ }
+ }
+ }
+
+ public void process(InboundWire source, OutboundWire target) {
+ SCAObject container = source.getContainer();
+ // Either Service or Reference
+ boolean isReference = container instanceof ReferenceBinding;
+
+ Map<Operation<?>, InboundInvocationChain> chains = source.getInvocationChains();
+ for (Map.Entry<Operation<?>, InboundInvocationChain> entry : chains.entrySet()) {
+ Operation<?> sourceOperation = entry.getKey();
+ Operation<?> targetOperation =
+ getTargetOperation(target.getInvocationChains().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
+ DataBindingInteceptor interceptor =
+ new DataBindingInteceptor(source, sourceOperation, targetOperation);
+ interceptor.setMediator(mediator);
+ if (isReference) {
+ // FIXME: We need a better way to position the interceptors
+ target.getInvocationChains().get(targetOperation).addInterceptor(0, interceptor);
+ Interceptor tail = entry.getValue().getTailInterceptor();
+ if (tail != null) {
+ // HACK to relink the bridging interceptor
+ tail.setNext(interceptor);
+ }
+ } else {
+ entry.getValue().addInterceptor(0, interceptor);
+ }
+
+ }
+ }
+ }
+
+ private Operation getTargetOperation(Set<Operation<?>> operations, String operationName) {
+ for (Operation<?> op : operations) {
+ if (op.getName().equals(operationName)) {
+ return op;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java
new file mode 100644
index 0000000000..10731f8c53
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.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.impl;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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;
+
+import org.osoa.sca.annotations.Constructor;
+
+/**
+ * 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(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public QName getXMLType() {
+ return DATA_BINDING;
+ }
+
+ public DataType load(CompositeComponent parent,
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java
new file mode 100644
index 0000000000..8bfeb534f3
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.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.databinding.impl;
+
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+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.idl.ElementInfo;
+import org.apache.tuscany.spi.model.WrapperInfo;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+
+import org.osoa.sca.annotations.Service;
+
+/**
+ * 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
+ */
+ @Autowire
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Autowire
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java
new file mode 100644
index 0000000000..0093c0de91
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.apache.tuscany.spi.annotation.Autowire;
+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;
+import org.osoa.sca.annotations.Scope;
+
+/**
+ * Default Mediator implementation
+ */
+@Scope("COMPOSITE")
+public class MediatorImpl implements Mediator {
+
+ private DataBindingRegistry dataBindingRegistry;
+
+ private TransformerRegistry transformerRegistry;
+
+ @Autowire
+ public void setTransformerRegistry(TransformerRegistry transformerRegistry) {
+ this.transformerRegistry = transformerRegistry;
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Autowire
+ 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) {
+ TransformationException ex = new TransformationException("No path found for the transformation");
+ ex.addContextName("Source: " + sourceId);
+ ex.addContextName("Target: " + targetId);
+ throw ex;
+ }
+ return path;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java
new file mode 100644
index 0000000000..aaca7d2b9c
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.apache.tuscany.spi.annotation.Autowire;
+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.idl.ElementInfo;
+import org.apache.tuscany.spi.model.WrapperInfo;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+import org.osoa.sca.annotations.Service;
+
+/**
+ * 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;
+
+ /**
+ * @param wrapperHandler
+ */
+ public Output2OutputTransformer() {
+ super();
+ }
+
+ /**
+ * @param mediator the mediator to set
+ */
+ @Autowire
+ public void setMediator(Mediator mediator) {
+ this.mediator = mediator;
+ }
+
+ /**
+ * @param dataBindingRegistry the dataBindingRegistry to set
+ */
+ @Autowire
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java
new file mode 100644
index 0000000000..c5a9a66731
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 java.util.Set;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.databinding.DataBinding;
+import org.apache.tuscany.spi.databinding.DataBindingRegistry;
+import org.apache.tuscany.spi.extension.AtomicComponentExtension;
+import org.apache.tuscany.spi.model.DataType;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.OutboundWire;
+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
+ */
+ @Autowire
+ public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) {
+ this.dataBindingRegistry = dataBindingRegistry;
+ }
+
+ public void process(OutboundWire source, InboundWire target) {
+ Interceptor tailInterceptor;
+ PassByValueInterceptor passByValueInterceptor;
+ Operation<?> targetOperation;
+ Operation<?> sourceOperation;
+ DataBinding[] argsDataBindings;
+ DataBinding resultDataBinding;
+
+ boolean allowsPassByReference = false;
+ if (target.getContainer() instanceof AtomicComponentExtension) {
+ allowsPassByReference =
+ ((AtomicComponentExtension) target.getContainer()).isAllowsPassByReference();
+ }
+ if (target.getServiceContract().isRemotable()
+ && !allowsPassByReference) {
+ Map<Operation<?>, InboundInvocationChain> chains = target.getInvocationChains();
+ for (Map.Entry<Operation<?>, InboundInvocationChain> entry : chains.entrySet()) {
+ targetOperation = entry.getKey();
+ sourceOperation =
+ getSourceOperation(source.getInvocationChains().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 = source.getInvocationChains().get(sourceOperation).getTailInterceptor();
+ if (tailInterceptor != null) {
+ tailInterceptor.setNext(passByValueInterceptor);
+ }
+ }
+ }
+ }
+
+ // Check if there's a callback
+ Map callbackOperations = source.getServiceContract().getCallbackOperations();
+ allowsPassByReference = false;
+ if (source.getContainer() instanceof AtomicComponentExtension) {
+ allowsPassByReference =
+ ((AtomicComponentExtension) source.getContainer()).isAllowsPassByReference();
+ }
+
+ if (source.getServiceContract().isRemotable()
+ && !allowsPassByReference
+ && callbackOperations != null
+ && !callbackOperations.isEmpty()) {
+ Object targetAddress = source.getContainer().getName();
+ Map<Operation<?>, InboundInvocationChain> callbackChains = source.getTargetCallbackInvocationChains();
+ for (Map.Entry<Operation<?>, InboundInvocationChain> entry : callbackChains.entrySet()) {
+ targetOperation = entry.getKey();
+ sourceOperation =
+ getSourceOperation(target.getSourceCallbackInvocationChains(targetAddress).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 =
+ target.getSourceCallbackInvocationChains(targetAddress).get(sourceOperation)
+ .getTailInterceptor();
+ if (tailInterceptor != null) {
+ tailInterceptor.setNext(passByValueInterceptor);
+ }
+ }
+ }
+ }
+
+ public void process(InboundWire source, OutboundWire target) {
+ //to be done if required..
+ }
+
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java
new file mode 100644
index 0000000000..0373ebcdfe
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.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.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.idl.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.java
new file mode 100644
index 0000000000..ec0560e878
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Transformer;
+import org.apache.tuscany.spi.databinding.extension.SimpleType2JavaTransformer;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Transformer to convert data from an simple Node to Java Object
+ */
+@Service(Transformer.class)
+public class Node2Object extends SimpleType2JavaTransformer<Node> {
+
+ public Node2Object() {
+ super(null);
+ }
+
+ @Override
+ protected String getText(Node source) {
+ if (source instanceof Document) {
+ source = ((Document)source).getDocumentElement();
+ }
+ return source.getTextContent();
+ }
+
+ public Class getSourceType() {
+ return Node.class;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.java
new file mode 100644
index 0000000000..7f472ba4ff
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.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.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.Transformer;
+import org.apache.tuscany.spi.databinding.extension.DOMHelper;
+import org.apache.tuscany.spi.databinding.extension.Java2SimpleTypeTransformer;
+import org.apache.tuscany.spi.idl.ElementInfo;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * Transformer to convert data from a simple java object to Node
+ */
+@Service(Transformer.class)
+public class Object2Node extends Java2SimpleTypeTransformer<Node> {
+
+ private Document factory;
+
+ public Object2Node() {
+ super(null);
+ try {
+ factory = DOMHelper.newDocument();
+ } catch (ParserConfigurationException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ protected Node createElement(ElementInfo element, String text, TransformationContext context) {
+ QName name = element.getQName();
+ Node root = DOMHelper.createElement(factory, name);
+ root.appendChild(factory.createTextNode(text));
+ return root;
+ }
+
+ public Class getTargetType() {
+ return Node.class;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java
new file mode 100644
index 0000000000..c931cccde9
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.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.deployer;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+
+/**
+ * Base class for DeploymentContext implementations.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractDeploymentContext implements DeploymentContext {
+ private final ClassLoader classLoader;
+ private final URL scdlLocation;
+ private final Map<String, Object> properties = new HashMap<String, Object>();
+
+ protected AbstractDeploymentContext(ClassLoader classLoader, URL scdlLocation) {
+ this.classLoader = classLoader;
+ this.scdlLocation = scdlLocation;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public URL getScdlLocation() {
+ return scdlLocation;
+ }
+
+ public Object getExtension(String name) {
+ return properties.get(name);
+ }
+
+ public void putExtension(String name, Object value) {
+ if (value == null) {
+ properties.remove(name);
+ } else {
+ properties.put(name, value);
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java
new file mode 100644
index 0000000000..c489ba04c3
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.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.deployer;
+
+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 specifying the loader for application resources.
+ *
+ * @param parent the parent of this context
+ * @param classLoader the loader for application resources
+ * @param scdlLocation the location of the SCDL being deployed
+ */
+ public ChildDeploymentContext(DeploymentContext parent, ClassLoader classLoader, URL scdlLocation) {
+ super(classLoader, scdlLocation);
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java
new file mode 100644
index 0000000000..303513f520
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.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;
+
+import javax.xml.stream.XMLInputFactory;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+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.component.Component;
+import org.apache.tuscany.spi.component.ComponentRegistrationException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.PrepareException;
+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.api.annotation.Monitor;
+import org.apache.tuscany.core.component.event.CompositeStop;
+import org.apache.tuscany.core.component.scope.CompositeScopeContainer;
+
+/**
+ * Default implementation of Deployer.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DeployerImpl implements Deployer {
+ private XMLInputFactory xmlFactory;
+ private Loader loader;
+ private Builder builder;
+ private ScopeContainerMonitor monitor;
+
+ public DeployerImpl(XMLInputFactory xmlFactory, Loader loader, Builder builder) {
+ this.xmlFactory = xmlFactory;
+ this.loader = loader;
+ this.builder = builder;
+ }
+
+ public DeployerImpl() {
+ xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ }
+
+ @Autowire
+ public void setLoader(LoaderRegistry loader) {
+ this.loader = loader;
+ }
+
+ @Autowire
+ public void setBuilder(BuilderRegistry builder) {
+ this.builder = builder;
+ }
+
+ @Monitor
+ public void setMonitor(ScopeContainerMonitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public <I extends Implementation<?>> Component deploy(CompositeComponent parent,
+ ComponentDefinition<I> componentDefinition)
+ throws LoaderException, BuilderException, PrepareException {
+ final ScopeContainer scopeContainer = new CompositeScopeContainer(monitor);
+ scopeContainer.start();
+ DeploymentContext deploymentContext = new RootDeploymentContext(null, xmlFactory, scopeContainer, null);
+ try {
+ load(parent, componentDefinition, deploymentContext);
+ } catch (LoaderException e) {
+ e.addContextName(componentDefinition.getName());
+ throw e;
+ }
+ 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 CompositeStop) {
+ scopeContainer.stop();
+ }
+ }
+ };
+ component.addListener(listener);
+ component.prepare();
+ try {
+ parent.register(component);
+ } catch (ComponentRegistrationException e) {
+ throw new BuilderInstantiationException("Error registering component", e);
+ }
+ return component;
+ }
+
+ /**
+ * 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(CompositeComponent parent,
+ ComponentDefinition<I> componentDefinition,
+ DeploymentContext deploymentContext) throws LoaderException {
+ loader.loadComponentType(parent, 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(CompositeComponent parent,
+ ComponentDefinition<I> componentDefinition,
+ DeploymentContext deploymentContext)
+ throws BuilderException {
+ return builder.build(parent, componentDefinition, deploymentContext);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java
new file mode 100644
index 0000000000..be5cc56d51
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.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.deployer;
+
+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 specifying the loader for application resources.
+ *
+ * @param classLoader the loader for application resources
+ * @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 scdlLocation the location of the SCDL being deployed
+ */
+ public RootDeploymentContext(ClassLoader classLoader,
+ XMLInputFactory xmlFactory,
+ ScopeContainer scopeContainer,
+ URL scdlLocation) {
+ super(classLoader, scdlLocation);
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java
new file mode 100644
index 0000000000..9c272af719
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.InteractionScope;
+import org.apache.tuscany.spi.model.ModelObject;
+
+import org.apache.tuscany.core.loader.StAXUtil;
+
+/**
+ * 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(XML_NAMESPACE_1_0, "interface.java");
+
+ private final JavaInterfaceProcessorRegistry interfaceRegsitry;
+
+ @Constructor({"registry", "interfaceRegsitry"})
+ public InterfaceJavaLoader(@Autowire LoaderRegistry registry,
+ @Autowire JavaInterfaceProcessorRegistry interfaceRegistry) {
+ super(registry);
+ this.interfaceRegsitry = interfaceRegistry;
+ }
+
+ public QName getXMLType() {
+ return INTERFACE_JAVA;
+ }
+
+ public JavaServiceContract load(CompositeComponent parent,
+ ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ assert INTERFACE_JAVA.equals(reader.getName());
+ InteractionScope interactionScope = StAXUtil.interactionScope(reader.getAttributeValue(null, "scope"));
+ 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(parent, 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.setInteractionScope(interactionScope);
+ return serviceContract;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java
new file mode 100644
index 0000000000..cd108ab238
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.EndConversation;
+import org.osoa.sca.annotations.OneWay;
+import org.osoa.sca.annotations.Remotable;
+import org.osoa.sca.annotations.Scope;
+
+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.InteractionScope;
+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 = false;
+ if (interactionScope != null && "CONVERSATION".equalsIgnoreCase(interactionScope.value())) {
+ contract.setInteractionScope(InteractionScope.CONVERSATIONAL);
+ conversational = true;
+ } else {
+ contract.setInteractionScope(InteractionScope.NONCONVERSATIONAL);
+ }
+ 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(EndConversation.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java
new file mode 100644
index 0000000000..3dd1328b6a
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.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.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.component.CompositeComponent;
+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(CompositeComponent parent, Class<?> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitClass(parent, clazz, type, context);
+ }
+
+ for (Constructor<?> constructor : clazz.getConstructors()) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitConstructor(parent, constructor, type, context);
+ }
+ }
+
+ Set<Method> methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz);
+ for (Method method : methods) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitMethod(parent, method, type, context);
+ }
+ }
+
+ Set<Field> fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz);
+ for (Field field : fields) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitField(parent, field, type, context);
+ }
+ }
+
+ Class superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ visitSuperClass(parent, superClass, type, context);
+ }
+
+ for (ImplementationProcessor processor : cache) {
+ processor.visitEnd(parent, clazz, type, context);
+ }
+ return type;
+ }
+
+ private void visitSuperClass(CompositeComponent parent,
+ Class<?> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ if (!Object.class.equals(clazz)) {
+ for (ImplementationProcessor processor : cache) {
+ processor.visitSuperClass(parent, clazz, type, context);
+ }
+ clazz = clazz.getSuperclass();
+ if (clazz != null) {
+ visitSuperClass(parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java
new file mode 100644
index 0000000000..4ef4dc4d49
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 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.OutboundWire;
+
+import org.apache.tuscany.core.injection.ArrayMultiplicityObjectFactory;
+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 {
+ 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;
+ private List<Class<?>> constructorParamTypes = new ArrayList<Class<?>>();
+
+ public PojoAtomicComponent(PojoConfiguration configuration) {
+ super(configuration.getName(),
+ configuration.getParent(),
+ configuration.getWireService(),
+ configuration.getWorkContext(),
+ configuration.getScheduler(),
+ configuration.getMonitor(),
+ 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.getCallbackSite() != null ? configuration.getCallbackSite()
+ : new HashMap<String, Member>();
+ implementationClass = configuration.getImplementationClass();
+ }
+
+
+ public boolean isDestroyable() {
+ return destroyInvoker != null;
+ }
+
+ public void init(Object instance) throws TargetInitializationException {
+ if (initInvoker != null) {
+ try {
+ initInvoker.invokeEvent(instance);
+ } catch (ObjectCallbackException e) {
+ throw new TargetInitializationException("Error initializing component instance", getName(), 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", getName(), 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 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
+ }
+
+ 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());
+ }
+ }
+
+ protected void onReferenceWire(OutboundWire wire) {
+ String name = wire.getReferenceName();
+ Member member = referenceSites.get(name);
+ if (member != null) {
+ injectors.add(createInjector(member, wire));
+ }
+ // 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] = createWireFactory(constructorParamTypes.get(i), wire);
+ break;
+ }
+ }
+ //TODO error if ref not set on constructor or ref site
+ }
+
+ public void onReferenceWires(List<OutboundWire> wires) {
+ assert wires.size() > 0 : "Wires were empty";
+ String referenceName = wires.get(0).getReferenceName();
+ Member member = referenceSites.get(referenceName);
+ if (member == null) {
+ if (constructorParamNames.contains(referenceName)) {
+ // injected on the constructor
+
+ } else {
+ throw new NoAccessorException(referenceName);
+ }
+ }
+ Class<?> type = wires.get(0).getServiceContract().getInterfaceClass();
+ if (type == null) {
+ throw new NoMultiplicityTypeException("Java interface must be specified for multiplicity", referenceName);
+ }
+ injectors.add(createMultiplicityInjector(member, type, wires));
+ //TODO multiplicity for constructor injection
+ }
+
+ 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, OutboundWire 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<OutboundWire> wireFactories) {
+ List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>();
+ for (OutboundWire 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());
+ }
+ }
+
+ protected abstract ObjectFactory<?> createWireFactory(Class<?> interfaze, OutboundWire wire);
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java
new file mode 100644
index 0000000000..104b1f647e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.extension.ExecutionMonitor;
+import org.apache.tuscany.spi.services.work.WorkScheduler;
+import org.apache.tuscany.spi.wire.WireService;
+
+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 String name;
+ private CompositeComponent parent;
+ //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 WireService wireService;
+ private WorkContext workContext;
+ private WorkScheduler scheduler;
+ private ExecutionMonitor monitor;
+ private long maxIdleTime = -1;
+ private long maxAge = -1;
+ private Class implementationClass;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public CompositeComponent getParent() {
+ return parent;
+ }
+
+ public void setParent(CompositeComponent parent) {
+ this.parent = parent;
+ }
+
+ 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> getCallbackSite() {
+ 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 WireService getWireService() {
+ return wireService;
+ }
+
+ public void setWireService(WireService wireService) {
+ this.wireService = wireService;
+ }
+
+ public WorkContext getWorkContext() {
+ return workContext;
+ }
+
+ public void setWorkContext(WorkContext workContext) {
+ this.workContext = workContext;
+ }
+
+ public WorkScheduler getScheduler() {
+ return scheduler;
+ }
+
+ public void setScheduler(WorkScheduler scheduler) {
+ this.scheduler = scheduler;
+ }
+
+ public ExecutionMonitor getMonitor() {
+ return monitor;
+ }
+
+ public void setMonitor(ExecutionMonitor monitor) {
+ this.monitor = monitor;
+ }
+
+ public Class getImplementationClass() {
+ return implementationClass;
+ }
+
+ public void setImplementationClass(Class implementationClass) {
+ this.implementationClass = implementationClass;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java
new file mode 100644
index 0000000000..965fde2fa8
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java
@@ -0,0 +1,71 @@
+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.ComponentRegistrationException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.Reference;
+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.BoundReferenceDefinition;
+import org.apache.tuscany.spi.model.BoundServiceDefinition;
+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 CompositeComponent build(CompositeComponent parent,
+ CompositeComponent component,
+ CompositeComponentType<?, ?, ?> componentType,
+ DeploymentContext deploymentContext) throws BuilderException {
+
+ for (ComponentDefinition<? extends Implementation<?>> definition : componentType.getComponents().values()) {
+ try {
+ Component child = builderRegistry.build(component, definition, deploymentContext);
+ component.register(child);
+ } catch (ComponentRegistrationException e) {
+ throw new BuilderInstantiationException("Error registering component", e);
+ }
+ }
+ for (ServiceDefinition definition : componentType.getServices().values()) {
+ try {
+ if (definition instanceof BoundServiceDefinition) {
+ BoundServiceDefinition bsd = (BoundServiceDefinition) definition;
+ Service service = builderRegistry.build(component, bsd, deploymentContext);
+ component.register(service);
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ } catch (ComponentRegistrationException e) {
+ throw new BuilderInstantiationException("Error registering service", e);
+ }
+ }
+ for (ReferenceDefinition definition : componentType.getReferences().values()) {
+ try {
+ if (definition instanceof BoundReferenceDefinition) {
+ BoundReferenceDefinition brd = (BoundReferenceDefinition) definition;
+ Reference child = builderRegistry.build(component, brd, deploymentContext);
+ component.register(child);
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ } catch (ComponentRegistrationException e) {
+ throw new BuilderInstantiationException("Error registering reference", e);
+ }
+ }
+ component.getExtensions().putAll(componentType.getExtensions());
+ return component;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java
new file mode 100644
index 0000000000..0f10703802
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.composite;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.w3c.dom.Document;
+
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.ComponentRegistrationException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.TargetInvokerCreationException;
+import org.apache.tuscany.spi.event.Event;
+import org.apache.tuscany.spi.extension.CompositeComponentExtension;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+import org.apache.tuscany.core.component.event.CompositeStart;
+import org.apache.tuscany.core.component.event.CompositeStop;
+
+/**
+ * The base implementation of a composite context
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractCompositeComponent 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;
+
+
+ /**
+ * @param name the name of the SCA composite
+ * @param parent the SCA composite parent
+ * @param connector the connector for fusing wires
+ * @param propertyValues the values of this composite's Properties
+ */
+ public AbstractCompositeComponent(String name,
+ CompositeComponent parent,
+ Connector connector,
+ Map<String, Document> propertyValues) {
+ super(name, parent, connector, propertyValues);
+ }
+
+ public <S, I extends S> void registerJavaObject(String name, Class<S> service, I instance)
+ throws ComponentRegistrationException {
+ register(new SystemSingletonAtomicComponent<S, I>(name, this, service, instance));
+ }
+
+ public <S, I extends S> void registerJavaObject(String name, List<Class<?>> services, I instance)
+ throws ComponentRegistrationException {
+ register(new SystemSingletonAtomicComponent<S, I>(name, this, services, instance));
+ }
+
+ public void start() {
+ synchronized (lock) {
+ if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) {
+ throw new IllegalStateException("Composite not in UNINITIALIZED state");
+ }
+
+ for (SCAObject child : systemChildren.values()) {
+ child.start();
+ }
+ for (SCAObject child : children.values()) {
+ child.start();
+ }
+ initializeLatch.countDown();
+ initialized = true;
+ lifecycleState = INITIALIZED;
+ }
+ publish(new CompositeStart(this, this));
+ }
+
+ public void stop() {
+ if (lifecycleState == STOPPED) {
+ return;
+ }
+
+ for (SCAObject child : children.values()) {
+ child.stop();
+ }
+ for (SCAObject child : systemChildren.values()) {
+ child.stop();
+ }
+ publish(new CompositeStop(this, this));
+ // 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);
+ }
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation, InboundWire callbackWire)
+ throws TargetInvokerCreationException {
+ return null;
+ }
+
+ /**
+ * 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(AbstractCompositeComponent.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java
new file mode 100644
index 0000000000..c571c04b3d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.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.implementation.composite;
+
+import org.osoa.sca.CompositeContext;
+import org.osoa.sca.ServiceRuntimeException;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.component.ServiceBinding;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WireService;
+
+/**
+ * Base implementation of the {@link org.osoa.sca.CompositeContext}
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractCompositeContext implements CompositeContext {
+ protected final CompositeComponent composite;
+ protected final WireService wireService;
+
+ public AbstractCompositeContext(final CompositeComponent composite, final WireService wireService) {
+ this.composite = composite;
+ this.wireService = wireService;
+ }
+
+ public String getName() {
+ return composite.getName();
+ }
+
+ public String getURI() {
+ throw new UnsupportedOperationException();
+ }
+
+ public <T> T locateService(Class<T> serviceInterface, String serviceName) throws ServiceRuntimeException {
+ QualifiedName qName = new QualifiedName(serviceName);
+ if (qName.getPortName() == null) {
+ String name = serviceInterface.getName();
+ qName = new QualifiedName(qName.getPartName(), name);
+ }
+ SCAObject child = composite.getChild(qName.getPartName());
+ InboundWire wire = getInboundWire(child, qName);
+ if (wire.isOptimizable()
+ && wire.getServiceContract().getInterfaceClass() != null
+ && serviceInterface.isAssignableFrom(wire.getServiceContract().getInterfaceClass())) {
+ try {
+ return serviceInterface.cast(wire.getTargetService());
+ } catch (TargetResolutionException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+ return wireService.createProxy(serviceInterface, wire);
+ }
+
+ protected InboundWire getInboundWire(SCAObject child, QualifiedName qName) {
+ InboundWire wire = null;
+ if (child instanceof Component) {
+ wire = ((Component) child).getInboundWire(qName.getPortName());
+ if (wire == null) {
+ throw new ServiceRuntimeException("Service not found [" + qName + "]");
+ }
+ } else if (child instanceof Service) {
+ Service service = (Service) child;
+ for (ServiceBinding binding : service.getServiceBindings()) {
+ if (Wire.LOCAL_BINDING.equals(binding.getInboundWire().getBindingType())) {
+ wire = binding.getInboundWire();
+ break;
+ }
+ }
+ if (wire == null) {
+ throw new ServiceRuntimeException("Local binding for service not found [" + qName + "]");
+ }
+ } else if (child instanceof Reference) {
+ Reference service = (Reference) child;
+ if (service.getReferenceBindings().isEmpty()) {
+ throw new ServiceRuntimeException("No binding for reference [" + qName + "]");
+ }
+ for (ReferenceBinding binding : service.getReferenceBindings()) {
+ if (Wire.LOCAL_BINDING.equals(binding.getInboundWire().getBindingType())) {
+ wire = binding.getInboundWire();
+ break;
+ }
+ }
+ if (wire == null) {
+ // pick the first one
+ wire = service.getReferenceBindings().get(0).getInboundWire();
+ }
+ } else if (child == null) {
+ throw new ServiceRuntimeException("Service not found [" + qName + "]");
+ } else {
+ throw new ServiceRuntimeException("Invalid service type [" + child.getClass().getName() + "]");
+ }
+ return wire;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java
new file mode 100644
index 0000000000..008c99db8d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.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.composite;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent,
+ ComponentDefinition<CompositeImplementation> componentDefinition,
+ DeploymentContext deploymentContext) throws BuilderException {
+ CompositeImplementation implementation = componentDefinition.getImplementation();
+ CompositeComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ String name = componentDefinition.getName();
+ CompositeComponentImpl component = new CompositeComponentImpl(name, parent, connector, null);
+
+ return build(parent, component, componentType, deploymentContext);
+ }
+
+ protected Class<CompositeImplementation> getImplementationType() {
+ return CompositeImplementation.class;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java
new file mode 100644
index 0000000000..75bc2d8c78
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.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.implementation.composite;
+
+import java.util.Map;
+
+import org.w3c.dom.Document;
+
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.CompositeComponent;
+
+/**
+ * The standard implementation of a composite component. Autowiring is performed by delegating to the parent composite.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeComponentImpl extends AbstractCompositeComponent {
+ private String uri;
+ private boolean systemComposite;
+
+ /**
+ * Constructor specifying property values
+ *
+ * @param name the name of this Component
+ * @param parent this component's parent
+ * @param connector the connector to use for wires
+ * @param propertyValues this composite's Property values
+ */
+ public CompositeComponentImpl(String name,
+ CompositeComponent parent,
+ Connector connector,
+ Map<String, Document> propertyValues) {
+ this(name, null, parent, connector, propertyValues);
+ }
+
+ /**
+ * Constructor specifying if the composite is a system composite
+ *
+ * @param name the name of this Component
+ * @param parent this component's parent
+ * @param connector the connector to use for wires
+ * @param systemComposite true if the composite is a system composite
+ */
+ public CompositeComponentImpl(String name,
+ CompositeComponent parent,
+ Connector connector,
+ boolean systemComposite) {
+ this(name, null, parent, connector, null, systemComposite);
+ }
+
+ /**
+ * Constructor specifying name and URI.
+ *
+ * @param name the name of this Component
+ * @param uri the unique identifier for this component
+ * @param parent this component's parent
+ * @param connector the connector to use for wires
+ * @param propertyValues this composite's Property values
+ */
+ public CompositeComponentImpl(String name,
+ String uri,
+ CompositeComponent parent,
+ Connector connector,
+ Map<String, Document> propertyValues) {
+ super(name, parent, connector, propertyValues);
+ this.uri = uri;
+ }
+
+ /**
+ * Constructor specifying name and URI.
+ *
+ * @param name the name of this Component
+ * @param uri the unique identifier for this component
+ * @param parent this component's parent
+ * @param connector the connector to use for wires
+ * @param propertyValues this composite's Property values
+ * @param systemComposite true if the composite is a system composite
+ */
+ public CompositeComponentImpl(String name,
+ String uri,
+ CompositeComponent parent,
+ Connector connector,
+ Map<String, Document> propertyValues,
+ boolean systemComposite) {
+ super(name, parent, connector, propertyValues);
+ this.uri = uri;
+ this.systemComposite = systemComposite;
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+ public boolean isSystem() {
+ return systemComposite;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java
new file mode 100644
index 0000000000..c55f1b8ffa
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.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.implementation.composite;
+
+import java.net.URL;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, CompositeImplementation implementation,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ URL scdlLocation = implementation.getScdlLocation();
+ ClassLoader cl = new CompositeClassLoader(implementation.getClassLoader());
+ deploymentContext = new ChildDeploymentContext(deploymentContext, cl, scdlLocation);
+ CompositeComponentType componentType = loadFromSidefile(parent, scdlLocation, deploymentContext);
+ implementation.setComponentType(componentType);
+ }
+
+ protected CompositeComponentType loadFromSidefile(CompositeComponent parent,
+ URL url,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ return loaderRegistry.load(parent, null, url, CompositeComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java
new file mode 100644
index 0000000000..b72c017cec
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java
@@ -0,0 +1,235 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Version.XML_NAMESPACE_1_0;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.model.BoundServiceDefinition;
+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(XML_NAMESPACE_1_0, "composite");
+ public static final String URI_DELIMITER = "/";
+
+ private final ArtifactRepository artifactRepository;
+
+ public CompositeLoader(@Autowire LoaderRegistry registry, @Autowire ArtifactRepository artifactRepository) {
+ super(registry);
+ this.artifactRepository = artifactRepository;
+ }
+
+ public QName getXMLType() {
+ return COMPOSITE;
+ }
+
+ public CompositeComponentType load(CompositeComponent parent,
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite =
+ new CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>();
+ composite.setName(reader.getAttributeValue(null, "name"));
+ boolean done = false;
+ while (!done) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(parent, composite, reader, deploymentContext);
+ if (o instanceof ServiceDefinition) {
+ composite.add((ServiceDefinition) o);
+ } else if (o instanceof ReferenceDefinition) {
+ composite.add((ReferenceDefinition) o);
+ } else if (o instanceof Property<?>) {
+ composite.add((Property<?>) o);
+ } else if (o instanceof ComponentDefinition<?>) {
+ composite.add((ComponentDefinition<?>) o);
+ } else if (o instanceof Include) {
+ composite.add((Include) o);
+ } else if (o instanceof Dependency) {
+ Artifact artifact = ((Dependency) o).getArtifact();
+ if (artifactRepository != null) {
+ // default to jar type if not specified
+ if (artifact.getType() == null) {
+ artifact.setType("jar");
+ }
+ artifactRepository.resolve(artifact);
+ }
+ if (artifact.getUrl() != null) {
+ 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) {
+ composite.add((WireDefinition) o);
+ } else {
+ // add as an unknown model extension
+ if (o != null) {
+ composite.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(composite);
+ verifyCompositeCompleteness(composite);
+ done = true;
+ break;
+ }
+ }
+ }
+ for (ComponentDefinition<? extends Implementation<?>> c : composite.getComponents().values()) {
+ PropertyHelper.processProperties(composite, c, deploymentContext);
+ }
+ return composite;
+ }
+
+ protected void resolveWires(CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite)
+ throws InvalidWireException {
+ QualifiedName sourceName;
+ 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);
+
+ sourceName = new QualifiedName(wire.getSource().getPath());
+ serviceDefinition = composite.getDeclaredServices().get(sourceName.getPartName());
+ if (serviceDefinition != null) {
+ if (serviceDefinition instanceof BoundServiceDefinition) {
+ ((BoundServiceDefinition) serviceDefinition).setTarget(wire.getTarget());
+ }
+ } else {
+ componentDefinition = composite.getDeclaredComponents().get(sourceName.getPartName());
+ if (componentDefinition != null) {
+ ReferenceTarget referenceTarget = createReferenceTarget(sourceName.getPortName(),
+ targetUri,
+ componentDefinition);
+ componentDefinition.add(referenceTarget);
+ } else {
+ throw new InvalidWireException("Source not found", sourceName.toString());
+ }
+ }
+ }
+ }
+
+ private ReferenceTarget createReferenceTarget(String 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.getName();
+ }
+ }
+
+ 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 instanceof BoundServiceDefinition && ((BoundServiceDefinition) svcDefn).getTarget() == null) {
+ throw new InvalidServiceException("Composite service not wired to a target", svcDefn.getName());
+ }
+ }
+ }
+
+ private void validateTarget(URI target,
+ CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite)
+ throws InvalidWireException {
+ QualifiedName targetName = new QualifiedName(target.getPath());
+ // if target is not a reference of the composite
+ if (composite.getReferences().get(targetName.getPartName()) == null) {
+ ComponentDefinition<?> targetDefinition = composite.getDeclaredComponents().get(targetName.getPartName());
+ // 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 (targetName.getPortName() == null) {
+ if (services.size() > 1 || services.isEmpty()) {
+ throw new InvalidWireException("Ambiguous target", targetName.toString());
+ }
+ } else {
+ if (services.get(targetName.getPortName()) == null) {
+ throw new InvalidWireException("Invalid target service", targetName.toString());
+ }
+ }
+ } else {
+ throw new InvalidWireException("Target not found", targetName.toString());
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java
new file mode 100644
index 0000000000..c814691185
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.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.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.Version;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(Version.XML_NAMESPACE_1_0, "implementation.composite");
+
+ private final ArtifactRepository artifactRepository;
+
+ public ImplementationCompositeLoader(@Autowire LoaderRegistry registry,
+ @Autowire ArtifactRepository artifactRepository) {
+ super(registry);
+ this.artifactRepository = artifactRepository;
+ }
+
+ public QName getXMLType() {
+ return IMPLEMENTATION_COMPOSITE;
+ }
+
+ public CompositeImplementation load(CompositeComponent parent,
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedCompositeContext.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedCompositeContext.java
new file mode 100644
index 0000000000..544eb75cdd
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedCompositeContext.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.implementation.composite;
+
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.ServiceReference;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.wire.WireService;
+
+/**
+ * The default implementation of a {@link org.osoa.sca.CompositeContext} injected on a component implementation
+ * instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class ManagedCompositeContext extends AbstractCompositeContext {
+
+ /**
+ * Constructor.
+ *
+ * @param composite the parent composite of the component whose instance the current context is injected on
+ * @param wireService the wire service to use for generating proxies
+ */
+ public ManagedCompositeContext(final CompositeComponent composite, final WireService wireService) {
+ super(composite, wireService);
+ }
+
+ public String getName() {
+ return composite.getName();
+ }
+
+ public String getURI() {
+ throw new UnsupportedOperationException();
+ }
+
+ public RequestContext getRequestContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference createServiceReferenceForSession(Object self) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference createServiceReferenceForSession(Object self, String serviceName) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference newSession(String serviceName) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference newSession(String serviceName, Object sessionId) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void start() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void stop() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java
new file mode 100644
index 0000000000..9bc07582ee
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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 ServiceReference getServiceReference() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java
new file mode 100644
index 0000000000..3fcba7b054
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.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.implementation.composite;
+
+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.CompositeComponent;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.model.Scope;
+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>();
+ private boolean system;
+
+ public ReferenceImpl(String name, CompositeComponent parent, ServiceContract<?> contract) {
+ this(name, parent, contract, false);
+ }
+
+ public ReferenceImpl(String name,
+ CompositeComponent parent,
+ ServiceContract<?> contract,
+ boolean system) {
+ super(name, parent);
+ this.serviceContract = contract;
+ this.system = system;
+ }
+
+ public Scope getScope() {
+ return Scope.SYSTEM;
+ }
+
+ public ServiceContract<?> getServiceContract() {
+ return serviceContract;
+ }
+
+ public List<ReferenceBinding> getReferenceBindings() {
+ return Collections.unmodifiableList(bindings);
+ }
+
+ public void addReferenceBinding(ReferenceBinding binding) {
+ binding.setReference(this);
+ 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();
+ }
+ }
+
+ @Override
+ public boolean isSystem() {
+ return system;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java
new file mode 100644
index 0000000000..2db8519ccc
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.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.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.CompositeComponent;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.component.ServiceBinding;
+import org.apache.tuscany.spi.model.Scope;
+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 boolean system;
+ private URI targetUri;
+
+ public ServiceImpl(String name, CompositeComponent parent, ServiceContract<?> contract) {
+ this(name, parent, contract, null, false);
+ }
+
+ public ServiceImpl(String name,
+ CompositeComponent parent,
+ ServiceContract<?> contract,
+ URI targetUri,
+ boolean system) {
+ super(name, parent);
+ this.serviceContract = contract;
+ this.system = system;
+ this.targetUri = targetUri;
+ }
+
+ public Scope getScope() {
+ return Scope.SYSTEM;
+ }
+
+ public ServiceContract<?> getServiceContract() {
+ return serviceContract;
+ }
+
+ public URI getTargetUri() {
+ return targetUri;
+ }
+
+ public List<ServiceBinding> getServiceBindings() {
+ return Collections.unmodifiableList(bindings);
+ }
+
+ public void addServiceBinding(ServiceBinding binding) {
+ binding.setService(this);
+ 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();
+ }
+ }
+
+ @Override
+ public boolean isSystem() {
+ return system;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java
new file mode 100644
index 0000000000..82fb5bf62e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.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.implementation.composite;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.builder.BuilderRegistry;
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.services.management.TuscanyManagementService;
+
+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> {
+ private TuscanyManagementService managementService;
+
+ public SystemCompositeBuilder() {
+ }
+
+ public SystemCompositeBuilder(BuilderRegistry builderRegistry,
+ Connector connector,
+ TuscanyManagementService managementService) {
+ this.builderRegistry = builderRegistry;
+ this.connector = connector;
+ this.managementService = managementService;
+ }
+
+ public CompositeComponent build(CompositeComponent parent,
+ ComponentDefinition<SystemCompositeImplementation> componentDefinition,
+ DeploymentContext deploymentContext) throws BuilderException {
+ SystemCompositeImplementation impl = componentDefinition.getImplementation();
+ CompositeComponentType<?, ?, ?> componentType = impl.getComponentType();
+ String name = componentDefinition.getName();
+ CompositeComponent component = new CompositeComponentImpl(name, parent, connector, true);
+ component.setManagementService(managementService);
+ build(parent, component, componentType, deploymentContext);
+ return component;
+ }
+
+ protected Class<SystemCompositeImplementation> getImplementationType() {
+ return SystemCompositeImplementation.class;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java
new file mode 100644
index 0000000000..c8c14e2fad
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.composite;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.idl.java.JavaServiceContract;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.WireService;
+
+import org.apache.tuscany.core.wire.jdk.JDKWireService;
+
+/**
+ * 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 Map<String, InboundWire> inboundWires;
+ private WireService wireService = new JDKWireService();
+
+ public SystemSingletonAtomicComponent(String name, CompositeComponent parent, Class<S> interfaze, T instance) {
+ super(name, parent);
+ this.instance = instance;
+ inboundWires = new HashMap<String, InboundWire>();
+ initWire(interfaze);
+ }
+
+
+ public SystemSingletonAtomicComponent(String name,
+ CompositeComponent parent,
+ List<Class<?>> services,
+ T instance) {
+ super(name, parent);
+ this.instance = instance;
+ inboundWires = new HashMap<String, InboundWire>();
+ for (Class<?> interfaze : services) {
+ initWire(interfaze);
+ }
+ }
+
+ 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 void addInboundWire(InboundWire wire) {
+ inboundWires.put(wire.getServiceName(), wire);
+ }
+
+ public Collection<InboundWire> getInboundWires() {
+ return Collections.unmodifiableCollection(inboundWires.values());
+ }
+
+ public InboundWire getInboundWire(String serviceName) {
+ return inboundWires.get(serviceName);
+ }
+
+ public void addOutboundWire(OutboundWire wire) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void addOutboundWires(List<OutboundWire> wires) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Map<String, List<OutboundWire>> getOutboundWires() {
+ return Collections.emptyMap();
+ }
+
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation, InboundWire callbackWire) {
+ return null;
+ }
+
+ public boolean isSystem() {
+ return true;
+ }
+
+ private void initWire(Class<?> interfaze) {
+ JavaServiceContract serviceContract = new JavaServiceContract(interfaze);
+ ServiceDefinition def = new ServiceDefinition(interfaze.getName(), serviceContract, false);
+ InboundWire wire = wireService.createWire(def);
+ wire.setContainer(this);
+ inboundWires.put(wire.getServiceName(), wire);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java
new file mode 100644
index 0000000000..bc087dd4c2
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.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.implementation.java;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.core.wire.WireObjectFactory;
+
+import org.apache.tuscany.core.implementation.PojoAtomicComponent;
+import org.apache.tuscany.core.implementation.PojoConfiguration;
+import org.apache.tuscany.core.injection.CallbackWireObjectFactory;
+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.MethodInjector;
+
+/**
+ * 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, InboundWire callbackWire) {
+ Method[] methods;
+ Class callbackClass = null;
+ if (operation.isCallback()) {
+ callbackClass = operation.getServiceContract().getCallbackClass();
+ methods = callbackClass.getMethods();
+
+ } else {
+ methods = operation.getServiceContract().getInterfaceClass().getMethods();
+ }
+ Method method = findMethod(operation, methods);
+ return new JavaTargetInvoker(method, this, callbackWire, callbackClass, workContext, monitor);
+ }
+
+ protected void onServiceWire(InboundWire wire) {
+ String name = wire.getCallbackReferenceName();
+ if (name == null) {
+ // It's ok not to have one, we just do nothing
+ return;
+ }
+ Member member = callbackSites.get(name);
+ if (member != null) {
+ injectors.add(createCallbackInjector(member, wire.getServiceContract(), wire));
+ }
+ }
+
+ protected Injector<Object> createCallbackInjector(Member member,
+ ServiceContract<?> contract,
+ InboundWire inboundWire) {
+ if (member instanceof Field) {
+ Field field = (Field) member;
+ ObjectFactory<?> factory = new CallbackWireObjectFactory(field.getType(), wireService, inboundWire);
+ return new FieldInjector<Object>(field, factory);
+ } else if (member instanceof Method) {
+ Method method = (Method) member;
+ Class<?> type = method.getParameterTypes()[0];
+ ObjectFactory<?> factory = new CallbackWireObjectFactory(type, wireService, inboundWire);
+ return new MethodInjector<Object>(method, factory);
+ } else {
+ throw new InvalidAccessorException("Member must be a field or method", member.getName());
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ protected ObjectFactory<?> createWireFactory(Class<?> interfaze, OutboundWire wire) {
+ return new WireObjectFactory(interfaze, wire, wireService);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java
new file mode 100644
index 0000000000..4f97965da9
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.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.implementation.java;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.builder.BuilderConfigException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.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;
+
+ @Autowire
+ public void setHost(ResourceHost host) {
+ this.host = host;
+ }
+
+ @SuppressWarnings("unchecked")
+ public AtomicComponent build(CompositeComponent parent,
+ ComponentDefinition<JavaImplementation> definition,
+ DeploymentContext deployment) throws BuilderConfigException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ definition.getImplementation().getComponentType();
+
+ PojoConfiguration configuration = new PojoConfiguration();
+ configuration.setParent(parent);
+ 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.setWireService(wireService);
+ configuration.setWorkContext(workContext);
+ configuration.setScheduler(workScheduler);
+ 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.getName(), 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.setMonitor(monitor);
+ configuration.setName(definition.getName());
+ JavaAtomicComponent component = new JavaAtomicComponent(configuration);
+
+ // handle properties
+ handleProperties(definition, component);
+
+ // handle resources
+ handleResources(componentType, component, parent);
+
+ handleCallbackSites(componentType, configuration);
+
+ // FIXME JFM this should be refactored to be by operation
+ component.setAllowsPassByReference(componentType.isAllowsPassByReference());
+
+ 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
+ if (service.getCallbackReferenceName() != null) {
+ // Only if there is a callback reference in the service
+ configuration.addCallbackSite(service.getCallbackReferenceName(), service.getCallbackMember());
+ }
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private void handleResources(
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType,
+ JavaAtomicComponent component,
+ CompositeComponent parent) {
+ for (Resource resource : componentType.getResources().values()) {
+ ObjectFactory<?> objectFactory = resource.getObjectFactory();
+ if (objectFactory != null) {
+ component.addResourceFactory(resource.getName(), objectFactory);
+ } else {
+ 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, parent, host);
+ } else {
+ factory = new ResourceObjectFactory<Object>(type, mappedName, optional, parent, host);
+ }
+ component.addResourceFactory(name, factory);
+ }
+ }
+ }
+
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java
new file mode 100644
index 0000000000..ddfef5a2a2
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.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.implementation.java;
+
+import java.net.URL;
+
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(@Autowire LoaderRegistry loaderRegistry,
+ @Autowire IntrospectionRegistry introspector) {
+ super(loaderRegistry);
+ this.introspector = introspector;
+ }
+
+ @Override
+ protected Class<JavaImplementation> getImplementationClass() {
+ return JavaImplementation.class;
+ }
+
+ public void load(CompositeComponent parent,
+ 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(parent, implementation, deploymentContext);
+ } else {
+ componentType = loadFromSidefile(parent, resource, deploymentContext);
+ }
+ implementation.setComponentType(componentType);
+ }
+
+ protected PojoComponentType loadByIntrospection(CompositeComponent parent,
+ JavaImplementation implementation,
+ DeploymentContext deploymentContext) throws ProcessingException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>();
+ Class<?> implClass = implementation.getImplementationClass();
+ introspector.introspect(parent, implClass, componentType, deploymentContext);
+ return componentType;
+ }
+
+ protected PojoComponentType loadFromSidefile(CompositeComponent parent,
+ URL url,
+ DeploymentContext deploymentContext) throws LoaderException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>();
+ return loaderRegistry.load(parent, componentType, url, PojoComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java
new file mode 100644
index 0000000000..807db532fe
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.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.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 Class<?> implementationClass;
+
+ public Class<?> getImplementationClass() {
+ return implementationClass;
+ }
+
+ public void setImplementationClass(Class<?> implementationClass) {
+ this.implementationClass = implementationClass;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java
new file mode 100644
index 0000000000..2ba538486d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.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.java;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderUtil;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.annotation.Autowire;
+
+public class JavaImplementationLoader extends LoaderExtension {
+ public static final QName IMPLEMENTATION_JAVA = new QName(XML_NAMESPACE_1_0, "implementation.java");
+
+ @Constructor({"registry"})
+ public JavaImplementationLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ @Override
+ public QName getXMLType() {
+ return IMPLEMENTATION_JAVA;
+ }
+
+ public ModelObject load(CompositeComponent parent, ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+ assert IMPLEMENTATION_JAVA.equals(reader.getName());
+ JavaImplementation implementation = new JavaImplementation();
+ String implClass = reader.getAttributeValue(null, "class");
+ Class<?> implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader());
+ implementation.setImplementationClass(implementationClass);
+ registry.loadComponentType(parent, implementation, deploymentContext);
+ LoaderUtil.skipToEndElement(reader);
+ return implementation;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java
new file mode 100644
index 0000000000..6da60304fa
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.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.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.ExecutionMonitor;
+import org.apache.tuscany.spi.extension.TargetInvokerExtension;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.wire.InboundWire;
+
+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,
+ InboundWire wire,
+ Class callbackClass,
+ WorkContext context,
+ ExecutionMonitor monitor) {
+ super(wire, context, monitor);
+ assert operation != null : "Operation method cannot be null";
+ this.operation = operation;
+ this.component = component;
+ stateless = Scope.STATELESS == component.getScope();
+ this.callbackClass = callbackClass;
+ }
+
+ public JavaTargetInvoker(Method operation,
+ JavaAtomicComponent component,
+ InboundWire callbackWire,
+ WorkContext context,
+ ExecutionMonitor monitor) {
+ this(operation, component, callbackWire, null, context, monitor);
+ }
+
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java
new file mode 100644
index 0000000000..53ad52e110
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.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.processor;
+
+import org.osoa.sca.annotations.AllowsPassByReference;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ AllowsPassByReference annotation = clazz.getAnnotation(AllowsPassByReference.class);
+ if (annotation != null) {
+ type.setAllowsPassByReference(true);
+ } else {
+ type.setAllowsPassByReference(false);
+ }
+
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java
new file mode 100644
index 0000000000..f8fc449679
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(@Autowire ImplementationProcessorService service) {
+ this.service = service;
+ }
+
+ public <T> void visitClass(CompositeComponent parent, 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(CompositeComponent parent, 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, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java
new file mode 100644
index 0000000000..b0216e3d38
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.CompositeContext;
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.annotations.Context;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.spi.wire.WireService;
+
+import org.apache.tuscany.core.injection.CompositeContextObjectFactory;
+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 WireService wireService;
+ private WorkContext workContext;
+
+ @Autowire
+ public void setWireService(WireService wireService) {
+ this.wireService = wireService;
+ }
+
+ @Autowire
+ public void setWorkContext(WorkContext workContext) {
+ this.workContext = workContext;
+ }
+
+ public void visitMethod(CompositeComponent parent,
+ 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 (CompositeContext.class.equals(paramType)) {
+ String name = method.getName();
+ name = JavaIntrospectionHelper.toPropertyName(name);
+ Resource resource = new Resource();
+ resource.setName(name);
+ resource.setMember(method);
+ resource.setObjectFactory(new CompositeContextObjectFactory(parent, wireService));
+ type.getResources().put(name, resource);
+ } else if (RequestContext.class.equals(paramType)) {
+ String name = method.getName();
+ name = JavaIntrospectionHelper.toPropertyName(name);
+ Resource resource = new Resource();
+ resource.setName(name);
+ resource.setMember(method);
+ resource.setObjectFactory(new RequestContextObjectFactory(workContext));
+ type.getResources().put(name, resource);
+ } else {
+ throw new UnknownContextTypeException(paramType.getName());
+ }
+ }
+
+ public void visitField(CompositeComponent parent, Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ if (field.getAnnotation(Context.class) == null) {
+ return;
+ }
+ Class<?> paramType = field.getType();
+ if (CompositeContext.class.equals(paramType)) {
+ String name = field.getName();
+ Resource resource = new Resource();
+ resource.setName(name);
+ resource.setMember(field);
+ resource.setObjectFactory(new CompositeContextObjectFactory(parent, wireService));
+ type.getResources().put(name, resource);
+ } else if (RequestContext.class.equals(paramType)) {
+ String name = field.getName();
+ name = JavaIntrospectionHelper.toPropertyName(name);
+ Resource resource = new Resource();
+ resource.setName(name);
+ resource.setMember(field);
+ resource.setObjectFactory(new RequestContextObjectFactory(workContext));
+ type.getResources().put(name, resource);
+ } else {
+ throw new UnknownContextTypeException(paramType.getName());
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java
new file mode 100644
index 0000000000..e3a173ea06
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.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.implementation.processor;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.osoa.sca.annotations.Conversation;
+import org.osoa.sca.annotations.ConversationID;
+import org.osoa.sca.annotations.Scope;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent,
+ Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ Conversation conversation = clazz.getAnnotation(Conversation.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 @Conversation 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(CompositeComponent parent, 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(CompositeComponent parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java
new file mode 100644
index 0000000000..7ef540432f
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.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.processor;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.osoa.sca.annotations.Destroy;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java
new file mode 100644
index 0000000000..9c8858b78c
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.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.implementation.processor;
+
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, Class<T> clazz,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ super.visitClass(parent, 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(annotation.value());
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java
new file mode 100644
index 0000000000..bdf5d23ea8
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java
@@ -0,0 +1,546 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Remotable;
+import org.osoa.sca.annotations.Service;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.idl.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 org.apache.tuscany.spi.model.OverrideOptions;
+
+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(@Autowire ImplementationProcessorService service) {
+ this.implService = service;
+ }
+
+ public <T> void visitEnd(
+ CompositeComponent parent,
+ 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.getName(), 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.getName(), 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, 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.getName();
+ // 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.setOverride(OverrideOptions.MAY);
+ 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.getName(), 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java
new file mode 100644
index 0000000000..3f5505f7f0
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.List;
+import javax.xml.namespace.QName;
+
+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.osoa.sca.annotations.Resource;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.idl.InvalidServiceContractException;
+import org.apache.tuscany.spi.idl.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.OverrideOptions;
+import org.apache.tuscany.spi.model.ServiceContract;
+
+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(@Autowire JavaInterfaceProcessorRegistry registry) {
+ this.registry = registry;
+ }
+
+ public JavaMappedService createService(Class<?> interfaze) throws InvalidServiceContractException {
+ JavaMappedService service = new JavaMappedService();
+ service.setName(interfaze.getName());
+ 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,
+ Annotation[] paramAnnotations,
+ String[] constructorNames,
+ int pos,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ List<String> injectionNames) throws ProcessingException {
+ boolean processed = false;
+ for (Annotation annot : paramAnnotations) {
+ if (Autowire.class.equals(annot.annotationType())) {
+ processed = true;
+ processAutowire(annot, constructorNames, pos, param, type, injectionNames);
+ } else if (Property.class.equals(annot.annotationType())) {
+ processed = true;
+ processProperty(annot, constructorNames, pos, type, param, injectionNames);
+ } else if (Reference.class.equals(annot.annotationType())) {
+ processed = true;
+ processReference(annot, constructorNames, pos, type, param, 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(Autowire.class) || 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.setName(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 autowire metadata for a constructor parameter
+ *
+ * @param annot the autowire 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 param the parameter type
+ * @param type the component type associated with the implementation being processed
+ * @param injectionNames the collection of injection names to update
+ * @throws InvalidAutowireException
+ * @throws InvalidConstructorException
+ */
+ private void processAutowire(
+ Annotation annot,
+ String[] constructorNames,
+ int pos,
+ Class<?> param,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ List<String> injectionNames) throws ProcessingException {
+ // the param is marked as an autowire
+ Autowire autowireAnnot = (Autowire) annot;
+ JavaMappedReference reference = new JavaMappedReference();
+ reference.setAutowire(true);
+ String name = autowireAnnot.name();
+ if (name == null || name.length() == 0) {
+ if (constructorNames.length > 1 && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) {
+ throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at "
+ + (pos + 1));
+ } else if (constructorNames.length == 1 && constructorNames[0].length() == 0) {
+ // special case when @Constructor present with all autowire params not specifying any name
+ name = param.getName() + String.valueOf(pos);
+ } else if (constructorNames.length == 1
+ && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) {
+ throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at "
+ + (pos + 1));
+ } else if (constructorNames.length == 1 && constructorNames[0].length() > 0) {
+ name = constructorNames[pos];
+ } else if (constructorNames.length == 0 || constructorNames[pos].length() == 0) {
+ name = param.getName() + String.valueOf(pos);
+ } 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 autowire name",
+ paramNum);
+ }
+ reference.setName(name);
+ reference.setRequired(autowireAnnot.required());
+ ServiceContract<?> contract = null;
+ try {
+ contract = registry.introspect(param);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+
+// ServiceContract<?> contract = new JavaServiceContract();
+ contract.setInterfaceClass(param);
+ reference.setServiceContract(contract);
+ type.getReferences().put(name, reference);
+ addName(injectionNames, pos, name);
+ }
+
+ /**
+ * 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
+ */
+ private <T> void processProperty(
+ Annotation annot,
+ String[] constructorNames,
+ int pos,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ Class<T> param,
+ List<String> explicitNames) throws ProcessingException {
+ // TODO multiplicity
+ // the param is marked as a property
+ Property propAnnot = (Property) annot;
+ JavaMappedProperty<T> property = new JavaMappedProperty<T>();
+ property.setJavaType(param);
+ 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.setOverride(OverrideOptions.valueOf(propAnnot.override().toUpperCase()));
+
+ String xmlType = propAnnot.xmlType();
+ if (xmlType != null && xmlType.length() != 0) {
+ property.setXmlType(QName.valueOf(xmlType));
+ } else {
+ TypeInfo typeInfo = typeMapper.getXMLType(property.getJavaType());
+ if (typeInfo != null) {
+ property.setXmlType(typeInfo.getQName());
+ }
+ }
+ property.setJavaType(param);
+ 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,
+ 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 < pos + 1 || constructorNames[pos] == null
+ || constructorNames[pos].length() == 0) {
+ throw new InvalidReferenceException("No name specified for reference 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 reference name",
+ paramNum);
+ }
+ if (type.getReferences().get(name) != null) {
+ throw new DuplicateReferenceException(name);
+ }
+ reference.setName(name);
+ reference.setRequired(refAnnotation.required());
+ try {
+ ServiceContract<?> contract = registry.introspect(param);
+ 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 {
+
+ org.apache.tuscany.spi.implementation.java.Resource resource =
+ new org.apache.tuscany.spi.implementation.java.Resource();
+ 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);
+ }
+ resource.setName(name);
+ resource.setOptional(resourceAnnot.optional());
+ resource.setType(param);
+ String mappedName = resourceAnnot.mappedName();
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.add(resource);
+ addName(explicitNames, pos, name);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java
new file mode 100644
index 0000000000..be5ac78008
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.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.processor;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.osoa.sca.annotations.Init;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java
new file mode 100644
index 0000000000..92a2a0923d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.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.apache.tuscany.spi.annotation.Autowire}
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidAutowireException extends ProcessingException {
+
+ public InvalidAutowireException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java
new file mode 100644
index 0000000000..6ab5a77d8e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.osoa.sca.annotations.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java
new file mode 100644
index 0000000000..e7acce2973
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.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.processor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(@Autowire MonitorFactory monitorFactory, @Autowire ImplementationProcessorService service) {
+ super(Monitor.class, service);
+ this.monitorFactory = monitorFactory;
+ }
+
+ protected String getName(Monitor annotation) {
+ return null;
+ }
+
+ protected <T> void initProperty(JavaMappedProperty<T> property,
+ Monitor annotation,
+ CompositeComponent parent,
+ DeploymentContext context) {
+ Class<T> javaType = property.getJavaType();
+ property.setDefaultValueFactory(new SingletonObjectFactory<T>(monitorFactory.getMonitor(javaType)));
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java
new file mode 100644
index 0000000000..09b3c7383d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.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.implementation.processor;
+
+import java.lang.reflect.Constructor;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.idl.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;
+import org.apache.tuscany.spi.model.OverrideOptions;
+import org.osoa.sca.annotations.Property;
+
+/**
+ * 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(@Autowire ImplementationProcessorService service) {
+ super(Property.class, service);
+ }
+
+ protected String getName(Property annotation) {
+ return annotation.name();
+ }
+
+ protected <T> void initProperty(JavaMappedProperty<T> property,
+ Property annotation,
+ CompositeComponent parent,
+ DeploymentContext context) {
+ property.setOverride(OverrideOptions.valueOf(annotation.override().toUpperCase()));
+ String xmlType = annotation.xmlType();
+ if (xmlType != null && xmlType.length() != 0) {
+ property.setXmlType(QName.valueOf(annotation.xmlType()));
+ } else {
+ TypeInfo type = typeMapper.getXMLType(property.getJavaType());
+ if (type != null) {
+ property.setXmlType(type.getQName());
+ }
+ }
+ }
+
+ public <T> void visitConstructor(CompositeComponent parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java
new file mode 100644
index 0000000000..1ee77f0a87
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.implementation.processor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.osoa.sca.annotations.Reference;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.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(@Autowire JavaInterfaceProcessorRegistry registry) {
+ this.regsitry = registry;
+ }
+
+ public void visitMethod(CompositeComponent parent, Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ Reference annotation = method.getAnnotation(Reference.class);
+ Autowire autowire = method.getAnnotation(Autowire.class);
+ boolean isAutowire = autowire != null;
+ if (annotation == null && !isAutowire) {
+ return; //Not a reference or autowire annotation.
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalReferenceException("Setter must have one parameter", method.toString());
+ }
+ //process autowire required first let reference override. or if conflicting should this fault?
+ boolean required = false;
+ if (isAutowire) {
+ required = autowire.required();
+ }
+
+ String name = null;
+
+ if (annotation != null) {
+ if (annotation.name() != null && annotation.name().length() > 0) {
+ name = annotation.name();
+ }
+ 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.setAutowire(isAutowire);
+ reference.setRequired(required);
+ reference.setName(name);
+ ServiceContract contract;
+ try {
+ contract = regsitry.introspect(method.getParameterTypes()[0]);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ reference.setServiceContract(contract);
+ type.getReferences().put(name, reference);
+ }
+
+ public void visitField(CompositeComponent parent, Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+ Reference annotation = field.getAnnotation(Reference.class);
+ boolean autowire = field.getAnnotation(Autowire.class) != null;
+ if (annotation == null && !autowire) {
+ return;
+ }
+ String name = field.getName();
+ boolean required = false;
+ if (annotation != null) {
+ if (annotation.name() != null) {
+ name = annotation.name();
+ }
+ 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.setAutowire(autowire);
+ reference.setName(name);
+ ServiceContract contract;
+ try {
+ contract = regsitry.introspect(field.getType());
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ reference.setServiceContract(contract);
+ type.getReferences().put(name, reference);
+ }
+
+ public <T> void visitConstructor(CompositeComponent parent, Constructor<T> constructor,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java
new file mode 100644
index 0000000000..c60e141f58
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.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.implementation.processor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, Method method,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context)
+ throws ProcessingException {
+ org.osoa.sca.annotations.Resource annotation = method.getAnnotation(org.osoa.sca.annotations.Resource.class);
+ if (annotation == null) {
+ return;
+ }
+ if (method.getParameterTypes().length != 1) {
+ throw new IllegalResourceException("Resource setter must have one parameter", method.toString());
+ }
+ 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 = new Resource();
+ resource.setMember(method);
+ resource.setType(method.getParameterTypes()[0]);
+ resource.setOptional(annotation.optional());
+ resource.setName(name);
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.add(resource);
+ }
+
+ public void visitField(CompositeComponent parent, Field field,
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ org.osoa.sca.annotations.Resource annotation = field.getAnnotation(org.osoa.sca.annotations.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);
+ }
+
+ String mappedName = annotation.mappedName();
+ Resource resource = new Resource();
+ resource.setMember(field);
+ resource.setType(field.getType());
+ resource.setOptional(annotation.optional());
+ resource.setName(name);
+ if (mappedName.length() > 0) {
+ resource.setMappedName(mappedName);
+ }
+ type.add(resource);
+ }
+
+ public <T> void visitConstructor(CompositeComponent parent, Constructor<T> constructor,
+ PojoComponentType<JavaMappedService, JavaMappedReference,
+ JavaMappedProperty<?>> type,
+ DeploymentContext context) throws ProcessingException {
+
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java
new file mode 100644
index 0000000000..634aff0377
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.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.processor;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java
new file mode 100644
index 0000000000..6f96c92006
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.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.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.Remotable;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.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.ImplementationProcessorService;
+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(@Autowire ImplementationProcessorService implService) {
+ this.implService = implService;
+ }
+
+ public <T> void visitClass(CompositeComponent parent, 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.getAnnotation(Remotable.class) != null) {
+ JavaMappedService service;
+ try {
+ service = implService.createService(interfaze);
+ } catch (InvalidServiceContractException e) {
+ throw new ProcessingException(e);
+ }
+ type.getServices().put(service.getName(), 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.getName(), service);
+ }
+ }
+
+
+ public void visitMethod(CompositeComponent parent,
+ 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(CompositeComponent parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java
new file mode 100644
index 0000000000..33cbbe1232
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.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.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.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.builder.BuilderConfigException;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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;
+ }
+
+ @Autowire
+ public void setHost(ResourceHost host) {
+ this.host = host;
+ }
+
+ @SuppressWarnings("unchecked")
+ public AtomicComponent build(CompositeComponent parent,
+ ComponentDefinition<SystemImplementation> definition,
+ DeploymentContext deploymentContext) throws BuilderConfigException {
+ PojoComponentType<ServiceDefinition, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ definition.getImplementation().getComponentType();
+
+ PojoConfiguration configuration = new PojoConfiguration();
+ configuration.setParent(parent);
+ 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.getName(), 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.getName());
+ 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, parent, host);
+ } else {
+ factory = new ResourceObjectFactory<Object>(type, mappedName, optional, parent, host);
+ }
+ component.addResourceFactory(name, factory);
+
+ }
+ return component;
+ }
+
+// private void processReferences(ComponentDefinition<SystemImplementation> definition,
+// Map<String, JavaMappedReference> references,
+// CompositeComponent parent,
+// SystemAtomicComponentImpl component) {
+// // no proxies needed for system components
+// for (ReferenceTarget target : definition.getReferenceTargets().values()) {
+// String referenceName = target.getReferenceName();
+// JavaMappedReference referenceDefiniton = references.get(referenceName);
+// Class interfaze = referenceDefiniton.getServiceContract().getInterfaceClass();
+// OutboundWire wire;
+// if (referenceDefiniton.isAutowire()) {
+// boolean required = referenceDefiniton.isRequired();
+// wire = new SystemOutboundAutowire(referenceName, interfaze, parent, required);
+// } else {
+// //FIXME support multiplicity!
+// assert target.getTargets().size() == 1 : "Multiplicity not yet implemented";
+// QualifiedName targetName = new QualifiedName(target.getTargets().get(0).getPath());
+// wire = new SystemOutboundWireImpl(referenceName, targetName, interfaze);
+// }
+// component.addOutboundWire(wire);
+// }
+// }
+
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java
new file mode 100644
index 0000000000..c43b0d1ee9
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.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.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.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+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, InboundWire callbackWire) {
+ return null;
+ }
+
+ public boolean isSystem() {
+ return true;
+ }
+
+ protected ObjectFactory<?> createWireFactory(Class<?> interfaze, OutboundWire wire) {
+ return new OptimizedWireObjectFactory(wire);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java
new file mode 100644
index 0000000000..2c7141044b
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.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.implementation.system.loader;
+
+import java.net.URL;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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;
+ }
+
+ //FIXME autowire to support multiple interfaces
+ @Autowire
+ public void setIntrospector(IntrospectionRegistry introspector) {
+ this.introspector = introspector;
+ }
+
+ public void load(CompositeComponent parent,
+ 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(parent, 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(CompositeComponent parent,
+ SystemImplementation implementation,
+ DeploymentContext deploymentContext) throws ProcessingException {
+ PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType =
+ new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>();
+ Class<?> implClass = implementation.getImplementationClass();
+ introspector.introspect(parent, implClass, componentType, deploymentContext);
+ return componentType;
+ }
+
+
+ protected PojoComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException {
+ return loaderRegistry.load(null, null, url, PojoComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java
new file mode 100644
index 0000000000..0e05041ea5
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.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.implementation.system.loader;
+
+import java.net.URL;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(CompositeComponent parent, SystemCompositeImplementation implementation,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ URL scdlLocation = implementation.getScdlLocation();
+ if (scdlLocation == null) {
+ throw new LoaderException("SCDL location not found");
+ }
+ ClassLoader cl = implementation.getClassLoader();
+ deploymentContext = new ChildDeploymentContext(deploymentContext, cl, scdlLocation);
+ CompositeComponentType componentType = loadFromSidefile(parent, scdlLocation, deploymentContext);
+ implementation.setComponentType(componentType);
+ }
+
+
+ protected CompositeComponentType loadFromSidefile(CompositeComponent parent,
+ URL url,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ return loaderRegistry.load(parent, null, url, CompositeComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java
new file mode 100644
index 0000000000..d5d4269880
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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/system/1.0-SNAPSHOT", "implementation.system");
+
+ public SystemImplementationLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public SystemImplementation load(CompositeComponent parent,
+ 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(parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java
new file mode 100644
index 0000000000..fc389a23cf
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.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.injection;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.WireService;
+
+/**
+ * Returns proxy instance for a wire callback
+ *
+ * @version $Rev$ $Date$
+ */
+public class CallbackWireObjectFactory implements ObjectFactory {
+
+ private WireService wireService;
+ private Class<?> interfaze;
+ private InboundWire wire;
+
+ public CallbackWireObjectFactory(Class<?> interfaze, WireService wireService, InboundWire wire) {
+ this.interfaze = interfaze;
+ this.wireService = wireService;
+ this.wire = wire;
+ }
+
+ public Object getInstance() throws ObjectCreationException {
+ return wireService.createCallbackProxy(interfaze, wire);
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java
new file mode 100644
index 0000000000..f904484e78
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.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 org.osoa.sca.CompositeContext;
+
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.wire.WireService;
+
+import org.apache.tuscany.core.implementation.composite.ManagedCompositeContext;
+
+/**
+ * Creates instances of {@link org.apache.tuscany.core.implementation.composite.ManagedCompositeContext} for injection
+ * on component implementation instances
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeContextObjectFactory implements ObjectFactory<CompositeContext> {
+ private CompositeComponent composite;
+ private WireService wireService;
+
+ public CompositeContextObjectFactory(CompositeComponent composite, WireService wireService) {
+ assert composite != null;
+ assert wireService != null;
+ this.composite = composite;
+ this.wireService = wireService;
+ }
+
+ public CompositeContext getInstance() throws ObjectCreationException {
+ return new ManagedCompositeContext(composite, wireService);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java
new file mode 100644
index 0000000000..aadd6297ea
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.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.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) {
+ String name = ctr.getName();
+ throw new ObjectCallbackException("Null object factory for constructor parameter [" + i + "]", name);
+ }
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java
new file mode 100644
index 0000000000..9a9d97a273
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java
@@ -0,0 +1,26 @@
+package org.apache.tuscany.core.injection;
+
+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<ManagedRequestContext> {
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java
new file mode 100644
index 0000000000..a68702157b
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.component.AtomicComponent;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.host.ResourceHost;
+import org.apache.tuscany.spi.host.ResourceResolutionException;
+import org.apache.tuscany.spi.wire.InboundWire;
+
+/**
+ * Resolves a runtime resource to be injected on a field or method of a Java component type marked with {@link
+ * org.osoa.sca.annotations.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 CompositeComponent parent;
+ private ResourceHost host;
+ private boolean resolveFromHost;
+ 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 parent the parent composite of the component to inject on
+ * @param host the runtime resource provider
+ */
+ public ResourceObjectFactory(Class<T> type,
+ boolean optional,
+ CompositeComponent parent,
+ ResourceHost host) {
+ this.type = type;
+ this.parent = parent;
+ this.host = host;
+ this.optional = optional;
+ }
+
+ /**
+ * 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 parent the parent composite of the component to inject on
+ * @param host the runtime resource provider
+ */
+ public ResourceObjectFactory(Class<T> type,
+ String mappedName,
+ boolean optional,
+ CompositeComponent parent,
+ ResourceHost host) {
+ this.type = type;
+ this.parent = parent;
+ this.host = host;
+ if (mappedName.indexOf("://") >= 0) {
+ this.resolveFromHost = true;
+ }
+ this.mappedName = mappedName;
+ this.optional = optional;
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public T getInstance() throws ObjectCreationException {
+ if (resolveFromHost) {
+ return resolveInstance();
+ } else {
+ T instance = null;
+ if (mappedName == null) {
+ try {
+ InboundWire wire = parent.resolveSystemAutowire(type);
+ if (wire != null) {
+ instance = (T) wire.getTargetService();
+ }
+ } catch (TargetResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+ if (instance == null) {
+ // if not found in parent scope, search the host namespace
+ resolveFromHost = true;
+ instance = resolveInstance();
+ }
+ if (instance == null && !optional) {
+ throw new ResourceNotFoundException("No resource found matching type", type.getName());
+ }
+ return instance;
+ } else {
+ SCAObject child = parent.getSystemChild(mappedName);
+ if (child instanceof AtomicComponent) {
+ try {
+ AtomicComponent component = (AtomicComponent) child;
+ instance = type.cast(component.getTargetInstance());
+ } catch (TargetResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+ } else if (child != null) {
+ throw new InvalidResourceTypeException("Invalid resource type", mappedName);
+ } else if (!optional) {
+ throw new ResourceNotFoundException("No resource found for URI", mappedName);
+ }
+ return instance;
+ }
+ }
+ }
+
+ private T resolveInstance() {
+ try {
+ if (mappedName == null) {
+ return host.resolveResource(type);
+ } else {
+ return host.resolveResource(type, mappedName);
+ }
+ } catch (ResourceResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java
new file mode 100644
index 0000000000..246ef8bdf7
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.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.launcher;
+
+import org.osoa.sca.RequestContext;
+import org.osoa.sca.ServiceReference;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.wire.WireService;
+
+import org.apache.tuscany.core.implementation.composite.AbstractCompositeContext;
+
+
+/**
+ * Default implementation of the {@link org.osoa.sca.CompositeContext} for non-managed code
+ *
+ * @version $Rev$ $Date$
+ */
+public class CompositeContextImpl extends AbstractCompositeContext {
+
+ public CompositeContextImpl(final CompositeComponent composite, final WireService wireService) {
+ super(composite, wireService);
+ }
+
+ public ServiceReference createServiceReferenceForSession(Object arg0) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference createServiceReferenceForSession(Object arg0, String arg1) {
+ throw new UnsupportedOperationException();
+ }
+
+ public RequestContext getRequestContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference newSession(String arg0) {
+ throw new UnsupportedOperationException();
+ }
+
+ public ServiceReference newSession(String arg0, Object arg1) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java
new file mode 100644
index 0000000000..730f29611a
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.launcher;
+
+import org.apache.tuscany.api.TuscanyException;
+
+/**
+ * Exception indicating that there was a problem launching an application.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class LaunchException extends TuscanyException {
+
+ protected LaunchException(String message) {
+ super(message);
+ }
+
+ protected LaunchException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ protected LaunchException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+
+ protected LaunchException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected LaunchException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java
new file mode 100644
index 0000000000..adf95a9bd9
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.launcher;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.stream.XMLInputFactory;
+
+import org.osoa.sca.CompositeContext;
+
+import org.apache.tuscany.spi.bootstrap.ComponentNames;
+import org.apache.tuscany.spi.bootstrap.RuntimeComponent;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeImplementation;
+import org.apache.tuscany.spi.services.management.TuscanyManagementService;
+
+import org.apache.tuscany.api.TuscanyException;
+import org.apache.tuscany.core.bootstrap.Bootstrapper;
+import org.apache.tuscany.core.bootstrap.DefaultBootstrapper;
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+import org.apache.tuscany.host.Launcher;
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.RuntimeInfo;
+import org.apache.tuscany.host.runtime.InitializationException;
+import org.apache.tuscany.host.monitor.FormatterRegistry;
+
+/**
+ * Basic launcher implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class LauncherImpl implements Launcher {
+ /**
+ * A conventional META-INF based location for the system SCDL.
+ *
+ * @see #bootRuntime(URL,MonitorFactory)
+ */
+ public static final String METAINF_SYSTEM_SCDL_PATH = "META-INF/tuscany/system.scdl";
+
+ /**
+ * A conventional META-INF based location for the application SCDL.
+ */
+ public static final String METAINF_APPLICATION_SCDL_PATH = "META-INF/sca/default.scdl";
+
+ private ClassLoader applicationLoader;
+
+ private RuntimeComponent runtime;
+
+ private Deployer deployer;
+
+ private CompositeComponent composite;
+
+ public void bootRuntime(URL systemScdl, ClassLoader systemClassLoader, MonitorFactory monitor)
+ throws TuscanyException {
+ if (systemScdl == null) {
+ throw new LoaderException("Null system SCDL URL");
+ }
+
+ XMLInputFactory xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", systemClassLoader);
+ TuscanyManagementService managementService = null;
+ Bootstrapper bootstrapper = new DefaultBootstrapper(monitor, xmlFactory, managementService);
+ Deployer bootDeployer = bootstrapper.createDeployer();
+
+ // create and start the core runtime
+ runtime = bootstrapper.createRuntime();
+ runtime.start();
+
+ // initialize the runtime info
+ CompositeComponent parent = runtime.getSystemComponent();
+ RuntimeInfo runtimeInfo = new LauncherRuntimeInfo(getInstallDirectory(), getApplicationRootDirectory(), true);
+ parent.registerJavaObject("RuntimeInfo", RuntimeInfo.class, runtimeInfo);
+
+ // register the monitor factory
+ if (monitor instanceof FormatterRegistry) {
+ List<Class<?>> interfazes = new ArrayList<Class<?>>(2);
+ interfazes.add(MonitorFactory.class);
+ interfazes.add(FormatterRegistry.class);
+ parent.registerJavaObject("MonitorFactory", interfazes, monitor);
+ } else {
+ parent.registerJavaObject("MonitorFactory", MonitorFactory.class, monitor);
+ }
+ parent.start();
+ // create a ComponentDefinition to represent the component we are going to deploy
+ SystemCompositeImplementation compositeImplementation = new SystemCompositeImplementation();
+ compositeImplementation.setScdlLocation(systemScdl);
+ compositeImplementation.setClassLoader(systemClassLoader);
+ ComponentDefinition<SystemCompositeImplementation> definition =
+ new ComponentDefinition<SystemCompositeImplementation>(
+ ComponentNames.TUSCANY_SYSTEM, compositeImplementation);
+ try {
+ // deploy the component into the runtime under the system parent
+ composite = (CompositeComponent) bootDeployer.deploy(parent, definition);
+ } catch (TuscanyException e) {
+ e.addContextName(definition.getName());
+ throw e;
+ }
+ // start the system
+ composite.start();
+
+ SCAObject child = composite.getSystemChild(ComponentNames.TUSCANY_DEPLOYER);
+ if (!(child instanceof AtomicComponent)) {
+ throw new InitializationException("Deployer must be an atomic component");
+ }
+ deployer = (Deployer) ((AtomicComponent) child).getTargetInstance();
+ runtime.getRootComponent().start();
+ }
+
+ /**
+ * Shuts down the active runtime being managed by this instance.
+ */
+ public void shutdownRuntime() {
+ if (composite != null) {
+ composite.stop();
+ composite = null;
+ }
+
+ if (runtime != null) {
+ runtime.stop();
+ runtime = null;
+ }
+ }
+
+ public CompositeContext bootApplication(URL applicationScdl, ClassLoader applicationLoader) {
+ // FIXME implement
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the classloader for application classes.
+ *
+ * @return the classloader for application classes
+ */
+ public ClassLoader getApplicationLoader() {
+ return applicationLoader;
+ }
+
+ /**
+ * Set the classloader to be used for application classes. You should almost always supply your own application
+ * classloader, based on the hosting environment that the runtime is embedded in.
+ *
+ * @param applicationLoader the classloader to be used for application classes
+ */
+ public void setApplicationLoader(ClassLoader applicationLoader) {
+ this.applicationLoader = applicationLoader;
+ }
+
+ /**
+ * Boots the runtime defined by the specified SCDL.
+ *
+ * @param systemScdl a resource path to the SCDL defining the system.
+ * @return a CompositeComponent for the newly booted runtime system
+ * @throws LoaderException
+ */
+ @Deprecated
+ public CompositeComponent bootRuntime(URL systemScdl, MonitorFactory monitor) throws TuscanyException {
+ ClassLoader systemClassLoader = getClass().getClassLoader();
+ bootRuntime(systemScdl, systemClassLoader, monitor);
+ return composite;
+ }
+
+ /**
+ * Boots the application defined by the specified SCDL.
+ *
+ * @param name the name of the application component
+ * @param appScdl URL to the SCDL defining the application
+ * @return a CompositeComponent for the newly booted application
+ * @throws LoaderException
+ */
+ @Deprecated
+ public CompositeComponent bootApplication(String name, URL appScdl) throws TuscanyException {
+ ClassLoader applicationLoader = getApplicationLoader();
+
+ if (appScdl == null) {
+ throw new LoaderException("No application scdl found");
+ }
+
+ // create a ComponentDefinition to represent the component we are going to deploy
+ CompositeImplementation impl = new CompositeImplementation();
+ impl.setScdlLocation(appScdl);
+ impl.setClassLoader(applicationLoader);
+ ComponentDefinition<CompositeImplementation> definition =
+ new ComponentDefinition<CompositeImplementation>(name, impl);
+
+ // deploy the component into the runtime under the system parent
+ CompositeComponent parent = runtime.getRootComponent();
+ // FIXME andyp -- this seems bogus when running inside an appserver
+ ClassLoader ccl = Thread.currentThread().getContextClassLoader();
+
+ try {
+
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ return (CompositeComponent) deployer.deploy(parent, definition);
+ } finally {
+ Thread.currentThread().setContextClassLoader(ccl);
+ }
+ }
+
+ public File getInstallDirectory() {
+ String property = System.getProperty("tuscany.installDir");
+ if (property != null) {
+ return new File(property);
+ }
+
+ // TODO: TUSCANY-648, should this throw an exception if it not running from a jar?
+
+ URL url = getClass().getResource("LauncherImpl.class");
+ String jarLocation = url.toString();
+ if ("jar".equals(url.getProtocol())) {
+ jarLocation = jarLocation.substring(4, jarLocation.lastIndexOf("!/"));
+ }
+ if (jarLocation.startsWith("file:")) {
+ jarLocation = jarLocation.substring(5);
+ }
+
+ File jarFile = new File(jarLocation);
+ return jarFile.getParentFile().getParentFile();
+ }
+
+ public File getApplicationRootDirectory() {
+ String property = System.getProperty("tuscany.applicationRootDir");
+ if (property != null) {
+ return new File(property);
+ }
+
+ return new File(System.getProperty("user.dir"));
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java
new file mode 100644
index 0000000000..a46631508b
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.launcher;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URI;
+
+import org.apache.tuscany.host.RuntimeInfo;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class LauncherRuntimeInfo implements RuntimeInfo {
+
+ /** Install directory */
+ private final File installDirectory;
+
+ /** Application root directory */
+ private final File applicationRootDirectory;
+
+ private final boolean online;
+
+ /**
+ * Initializes the installation and application root directories.
+ *
+ * @param installDirectory Installation directory.
+ * @param applicationRootDirectory Application root directory.
+ */
+ public LauncherRuntimeInfo(File installDirectory, File applicationRootDirectory, boolean online) {
+ this.installDirectory = installDirectory;
+ this.applicationRootDirectory = applicationRootDirectory;
+ this.online = online;
+ }
+
+ public URI getDomain() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Return the directory where the running runtime was installed.
+ *
+ * @return the directory where the runtime was installed
+ */
+ public File getInstallDirectory() {
+ return installDirectory;
+ }
+
+ /**
+ * Return the root directory used to resolve application file paths.
+ *
+ * @return the directory used to resolve application file paths.
+ */
+ public File getApplicationRootDirectory() {
+ return applicationRootDirectory;
+ }
+
+ /**
+ * Gets the base URL for the runtime.
+ *
+ * @return The base URL for the runtime.
+ */
+ public URL getBaseURL() {
+ try {
+ return installDirectory.toURL();
+ } catch (MalformedURLException e) {
+ // TODO Decide on how to handle the exception
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean isOnline() {
+ return online;
+ }
+
+ public String getRuntimeId() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java
new file mode 100644
index 0000000000..3b0a030987
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.URISyntaxException;
+import java.util.Map;
+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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.MissingMustOverridePropertyException;
+import org.apache.tuscany.spi.loader.MissingReferenceException;
+import org.apache.tuscany.spi.loader.NotOverridablePropertyException;
+import org.apache.tuscany.spi.loader.PropertyObjectFactory;
+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.BoundReferenceDefinition;
+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.OverrideOptions;
+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.implementation.system.model.SystemImplementation;
+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(XML_NAMESPACE_1_0, "component");
+ private static final QName PROPERTY = new QName(XML_NAMESPACE_1_0, "property");
+ private static final QName REFERENCE = new QName(XML_NAMESPACE_1_0, "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(@Autowire LoaderRegistry registry, @Autowire PropertyObjectFactory propertyFactory) {
+ super(registry);
+ this.propertyFactory = propertyFactory;
+ }
+
+ public QName getXMLType() {
+ return COMPONENT;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ComponentDefinition<?> load(CompositeComponent parent,
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ assert COMPONENT.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String initLevel = reader.getAttributeValue(null, "initLevel");
+
+ try {
+ Implementation<?> impl = loadImplementation(parent, reader, deploymentContext);
+ registry.loadComponentType(parent, impl, deploymentContext);
+
+ ComponentDefinition<Implementation<?>> componentDefinition =
+ new ComponentDefinition<Implementation<?>>(name, impl);
+
+ 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, deploymentContext, componentDefinition);
+ } else if (REFERENCE.equals(qname)) {
+ loadReference(reader, deploymentContext, componentDefinition);
+ } else {
+ throw new UnrecognizedElementException(qname);
+ }
+ reader.next();
+ break;
+ case END_ELEMENT:
+ if (reader.getName().equals(COMPONENT)) {
+ // hack to leave alone SystemImplementation
+ if (!((Implementation) componentDefinition
+ .getImplementation() instanceof SystemImplementation)) {
+ populatePropertyValues(componentDefinition);
+ }
+ ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> type =
+ (ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>) componentDefinition
+ .getImplementation().getComponentType();
+ for (ReferenceDefinition ref : type.getReferences().values()) {
+ if (ref.isAutowire()) {
+ ReferenceTarget referenceTarget = new ReferenceTarget();
+ referenceTarget.setReferenceName(ref.getName());
+ componentDefinition.add(referenceTarget);
+ }
+ }
+ validate(componentDefinition);
+ return componentDefinition;
+ }
+ break;
+ }
+ }
+ } catch (LoaderException e) {
+ e.addContextName(name);
+ throw e;
+ }
+ }
+
+ protected Implementation<?> loadImplementation(CompositeComponent parent,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+ reader.nextTag();
+ ModelObject o = registry.load(parent, null, reader, deploymentContext);
+ if (!(o instanceof Implementation)) {
+ throw new MissingImplementationException();
+ }
+ return (Implementation<?>) o;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void loadProperty(XMLStreamReader reader,
+ DeploymentContext deploymentContext,
+ ComponentDefinition<?> componentDefinition) throws XMLStreamException,
+ LoaderException {
+ String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR);
+ Implementation<?> implementation = componentDefinition.getImplementation();
+ ComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ Property<Type> property = (Property<Type>) componentType.getProperties().get(name);
+ if (property == null) {
+ throw new UndefinedPropertyException(name);
+ } else if (OverrideOptions.NO.equals(property.getOverride())) {
+ throw new NotOverridablePropertyException(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);
+ LoaderUtil.skipToEndElement(reader);
+ } else {
+ try {
+ DocumentBuilder documentBuilder = DOMHelper.newDocumentBuilder();
+ Document value = StAXUtil.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(new SimplePropertyObjectFactory(property, propertyValue.getValue()));
+ propertyValue.setValueFactory(objectFactory);
+ componentDefinition.add(propertyValue);
+ }
+
+ protected void loadReference(XMLStreamReader reader,
+ DeploymentContext deploymentContext,
+ ComponentDefinition<?> componentDefinition) throws XMLStreamException,
+ LoaderException {
+ String name = reader.getAttributeValue(null, "name");
+ String text = reader.getElementText();
+ String target = text != null ? text.trim() : null;
+
+
+ if (name == null) {
+ throw new InvalidReferenceException("No name specified");
+ } else if (target == null) {
+ throw new InvalidReferenceException("No target specified", name);
+ }
+ Implementation<?> impl = componentDefinition.getImplementation();
+ ComponentType<?, ?, ?> componentType = impl.getComponentType();
+ if (!componentType.getReferences().containsKey(name)) {
+ throw new UndefinedReferenceException(name);
+ }
+ if (componentType instanceof CompositeComponentType) {
+ ReferenceDefinition definition = componentType.getReferences().get(name);
+ assert definition instanceof BoundReferenceDefinition;
+ BoundReferenceDefinition brd = (BoundReferenceDefinition) definition;
+ if (brd.getBindings().isEmpty()) {
+ // TODO JFM allow selection of a default binding
+ try {
+ LocalBindingDefinition binding = new LocalBindingDefinition(new URI(target));
+ brd.addBinding(binding);
+ } catch (URISyntaxException e) {
+ throw new InvalidReferenceException(e);
+ }
+ } else {
+ for (BindingDefinition binding : brd.getBindings()) {
+ try {
+ // FIXME this is bad - clarify in the spec how URIs are overriden
+ binding.setTargetUri(new URI(target));
+ } catch (URISyntaxException e) {
+ throw new LoaderException(e);
+ }
+ }
+ }
+ } else {
+ ReferenceTarget referenceTarget = new ReferenceTarget();
+ referenceTarget.setReferenceName(name);
+ try {
+ referenceTarget.addTarget(new URI(target));
+ } catch (URISyntaxException e) {
+ throw new InvalidReferenceException(e);
+ }
+ componentDefinition.add(referenceTarget);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void populatePropertyValues(ComponentDefinition<Implementation<?>> componentDefinition)
+ throws MissingMustOverridePropertyException {
+ 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.getOverride() == OverrideOptions.MUST) {
+ throw new MissingMustOverridePropertyException(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.isAutowire() || !referenceDef.isRequired()) {
+ continue;
+ }
+ String name = referenceDef.getName();
+ if (!definition.getReferenceTargets().containsKey(name)) {
+ throw new MissingReferenceException(name);
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java
new file mode 100644
index 0000000000..3aa0d3fadc
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.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.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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(XML_NAMESPACE_1_0, "componentType");
+
+ @Constructor
+ public ComponentTypeElementLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return COMPONENT_TYPE;
+ }
+
+ @SuppressWarnings("unchecked")
+ public ComponentType load(CompositeComponent parent,
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) 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(parent, componentType, reader, deploymentContext);
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java
new file mode 100644
index 0000000000..66aafb6525
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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/1.0-SNAPSHOT";
+ 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(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return DEPENDENCY;
+ }
+
+ public Dependency load(CompositeComponent parent,
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java
new file mode 100644
index 0000000000..61146d5afd
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.URL;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(XML_NAMESPACE_1_0, "include");
+
+ @Constructor({"registry"})
+ public IncludeLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return INCLUDE;
+ }
+
+ public Include load(CompositeComponent parent, 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);
+ }
+
+ DeploymentContext childContext = new ChildDeploymentContext(deploymentContext, cl, url);
+ CompositeComponentType composite;
+ try {
+ composite = loadFromSidefile(parent, url, childContext);
+ } catch (LoaderException e) {
+ e.addContextName(name);
+ throw e;
+ }
+
+ Include include = new Include();
+ include.setName(name);
+ include.setScdlLocation(url);
+ include.setIncluded(composite);
+ return include;
+ }
+
+ protected CompositeComponentType loadFromSidefile(CompositeComponent parent,
+ URL url,
+ DeploymentContext deploymentContext)
+ throws LoaderException {
+ return registry.load(parent, null, url, CompositeComponentType.class, deploymentContext);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java
new file mode 100644
index 0000000000..4fad10c95f
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java
@@ -0,0 +1,50 @@
+package org.apache.tuscany.core.loader;
+
+import java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire 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());
+ } else {
+ writer.write("\n");
+ }
+ e.appendContextStack(writer).append("\n");
+ return writer;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java
new file mode 100644
index 0000000000..ee0fd27c55
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.component.CompositeComponent;
+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(CompositeComponent parent,
+ 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(parent, object, reader, deploymentContext);
+ }
+
+ public <MO extends ModelObject> MO load(CompositeComponent parent,
+ 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(parent, 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(CompositeComponent parent,
+ 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(parent, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java
new file mode 100644
index 0000000000..b232f6e3e2
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(XML_NAMESPACE_1_0, "policySet");
+
+ private static final QName INTENTMAP = new QName(XML_NAMESPACE_1_0, "intentMap");
+
+ private static final QName QUALIFIER = new QName(XML_NAMESPACE_1_0, "qualifier");
+
+ private static final QName POLICYSETREFERENCE = new QName(XML_NAMESPACE_1_0, "policySetReference");
+
+ private static final QName WSPOLICYATTACHMENT = new QName(WSPOLICY_NAMESPACE, "PolicyAttachment");
+
+ @Constructor({"registry"})
+ public PolicySetLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+
+ }
+
+ @Override
+ public QName getXMLType() {
+ return POLICYSET;
+ }
+
+ public PolicySet load(CompositeComponent parent, 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(XML_NAMESPACE_1_0, name), parseIntentName(provides));
+ String[] appliesToArtifact = split(appliesTo);
+ for (String artifact : appliesToArtifact) {
+ policySet.addAppliedArtifacts(new QName(XML_NAMESPACE_1_0, 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(XML_NAMESPACE_1_0, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java
new file mode 100644
index 0000000000..16c81caab7
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.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.loader;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import static org.osoa.sca.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+import org.w3c.dom.Document;
+
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.OverrideOptions;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ModelObject;
+import org.apache.tuscany.spi.annotation.Autowire;
+
+/**
+ * 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 PROPERTY_OVERRIDE_ATTR = "override";
+
+ public static final QName PROPERTY = new QName(XML_NAMESPACE_1_0, "property");
+ private final DocumentBuilder documentBuilder;
+
+ @Constructor({"registry"})
+ public PropertyLoader(@Autowire 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(CompositeComponent parent, 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 override = reader.getAttributeValue(null, PROPERTY_OVERRIDE_ATTR);
+
+ Document value = StAXUtil.createPropertyValue(reader, xmlType, documentBuilder);
+
+ Property<?> property = new Property();
+ property.setName(name);
+ property.setXmlType(xmlType);
+ property.setMany(many);
+
+ if (override != null) {
+ property.setOverride(OverrideOptions.valueOf(override.toUpperCase()));
+ }
+ property.setDefaultValue(value);
+ return property;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java
new file mode 100644
index 0000000000..eb3a030934
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.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 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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.BoundReferenceDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+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(XML_NAMESPACE_1_0, "reference");
+
+ @Constructor
+ public ReferenceLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return REFERENCE;
+ }
+
+ public ReferenceDefinition load(CompositeComponent parent,
+ ModelObject object, XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+ assert REFERENCE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ Multiplicity multiplicity =
+ StAXUtil.multiplicity(reader.getAttributeValue(null, "multiplicity"), Multiplicity.ONE_ONE);
+ List<BindingDefinition> bindings = new ArrayList<BindingDefinition>();
+ ServiceContract<?> contract = null;
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ ModelObject o = registry.load(parent, null, reader, deploymentContext);
+ if (o instanceof ServiceContract) {
+ contract = (ServiceContract) o;
+ } else if (o instanceof BindingDefinition) {
+ bindings.add((BindingDefinition) o);
+ } else {
+ throw new UnrecognizedElementException(reader.getName());
+ }
+ break;
+ case END_ELEMENT:
+ if (object instanceof ComponentType && !(object instanceof CompositeComponentType)) {
+ // loading a reference in a component type side file
+ ReferenceDefinition referenceDefinition = new ReferenceDefinition(name, contract);
+ referenceDefinition.setMultiplicity(multiplicity);
+ return referenceDefinition;
+ }
+ return new BoundReferenceDefinition(name, contract, bindings, multiplicity);
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java
new file mode 100644
index 0000000000..90a2be722f
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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.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.BoundServiceDefinition;
+import org.apache.tuscany.spi.model.ComponentType;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+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(XML_NAMESPACE_1_0, "service");
+ private static final QName REFERENCE = new QName(XML_NAMESPACE_1_0, "reference");
+
+ @Constructor
+ public ServiceLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return SERVICE;
+ }
+
+ public ServiceDefinition load(CompositeComponent parent,
+ ModelObject object,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext) throws XMLStreamException, LoaderException {
+ assert SERVICE.equals(reader.getName());
+ String name = reader.getAttributeValue(null, "name");
+ String target = null;
+ List<BindingDefinition> bindings = new ArrayList<BindingDefinition>();
+ ServiceContract serviceContract = null;
+ while (true) {
+ int i = reader.next();
+ switch (i) {
+ case START_ELEMENT:
+ // there is a reference already using this qname which doesn't seem appropriate.
+ if (REFERENCE.equals(reader.getName())) {
+ String text = reader.getElementText();
+ target = text != null ? text.trim() : null;
+ } else {
+ ModelObject o = registry.load(parent, null, reader, deploymentContext);
+ if (o instanceof ServiceContract) {
+ serviceContract = (ServiceContract) o;
+ } else if (o instanceof BindingDefinition) {
+ bindings.add((BindingDefinition) o);
+ } else {
+ throw new UnrecognizedElementException(reader.getName());
+ }
+ }
+ break;
+ case END_ELEMENT:
+ if (SERVICE.equals(reader.getName())) {
+ if (object instanceof ComponentType && !(object instanceof CompositeComponentType)) {
+ // the load is being done for an atomic component type
+ // FIXME need a way to specify "remotable" on a service
+ return new ServiceDefinition(name, serviceContract, false);
+ }
+ URI targetURI = null;
+ if (target != null) {
+ try {
+ targetURI = new URI(target);
+ } catch (URISyntaxException e) {
+ throw new InvalidReferenceException(target, name);
+ }
+ }
+ // FIXME need a way to specify "remotable" on a service
+ return new BoundServiceDefinition(name, serviceContract, bindings, false, targetURI);
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java
new file mode 100644
index 0000000000..50dee55c8e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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.apache.tuscany.spi.model.InteractionScope;
+import org.apache.tuscany.spi.model.Multiplicity;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * Utility classes to support StAX-based loaders
+ *
+ * @version $Rev$ $Date$
+ */
+public final class StAXUtil {
+ 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);
+ }
+
+ private StAXUtil() {
+ }
+
+ /**
+ * Convert a "multiplicity" attribute to the equivalent enum value.
+ *
+ * @param multiplicity the attribute to convert
+ * @param def the default value
+ * @return the enum equivalent
+ */
+ public static Multiplicity multiplicity(String multiplicity, Multiplicity def) {
+ return multiplicity == null ? def : MULTIPLICITY.get(multiplicity);
+ }
+
+ /**
+ * Convert a "scope" attribute to the equivalent enum value. Returns
+ * CONVERSATIONAL if the value equals (ignoring case) "conversational",
+ * otherwise returns NONCONVERSATIONAL.
+ *
+ * @param scope the attribute to convert
+ * @return the enum equivalent
+ */
+ public static InteractionScope interactionScope(String scope) {
+ if ("conversational".equalsIgnoreCase(scope)) {
+ return InteractionScope.CONVERSATIONAL;
+ } else {
+ return InteractionScope.NONCONVERSATIONAL;
+ }
+ }
+
+ 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
+ */
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java
new file mode 100644
index 0000000000..76b0858b94
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.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.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.Version.XML_NAMESPACE_1_0;
+import org.osoa.sca.annotations.Constructor;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+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(XML_NAMESPACE_1_0, "wire");
+ private static final QName SOURCE_URI = new QName(XML_NAMESPACE_1_0, "source.uri");
+ private static final QName TARGET_URI = new QName(XML_NAMESPACE_1_0, "target.uri");
+
+ @Constructor({"registry"})
+ public WireLoader(@Autowire LoaderRegistry registry) {
+ super(registry);
+ }
+
+ public QName getXMLType() {
+ return WIRE;
+ }
+
+ public WireDefinition load(CompositeComponent parent,
+ 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) {
+ sourceURI = new URI(uriString);
+ } 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) {
+ targetURI = new URI(uriString);
+ } 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java
new file mode 100644
index 0000000000..686c74c7f8
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.appendContextStack(e.appendBaseMessage(writer));
+ } else if (exception instanceof TuscanyRuntimeException) {
+ TuscanyRuntimeException e = (TuscanyRuntimeException) exception;
+ e.appendContextStack(e.appendBaseMessage(writer));
+ }
+ writer.append("\n");
+ return writer;
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java
new file mode 100644
index 0000000000..019dcbdcd3
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 java.io.StringWriter;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.WeakHashMap;
+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.api.annotation.LogLevel;
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.monitor.ExceptionFormatter;
+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 implements MonitorFactory, FormatterRegistry {
+ private String bundleName;
+ private Level defaultLevel;
+ private Map<String, Level> levels;
+ private List<ExceptionFormatter> formatters = new ArrayList<ExceptionFormatter>();
+ private ExceptionFormatter defaultFormatter = new DefaultExceptionFormatter();
+ private Map<Class<?>, WeakReference<?>> proxies = new WeakHashMap<Class<?>, WeakReference<?>>();
+
+ /**
+ * 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() {
+ }
+
+ public void initialize(Map<String, Object> configProperties) {
+ if (configProperties == null) {
+ return;
+ }
+ initInternal(configProperties);
+ }
+
+ private 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, bundleName);
+ proxies.put(monitorInterface, new WeakReference<T>(proxy));
+ }
+ return proxy;
+ }
+
+ private <T> T getCachedMonitor(Class<T> monitorInterface) {
+ WeakReference<?> ref = proxies.get(monitorInterface);
+ return (ref != null) ? monitorInterface.cast(ref.get()) : null;
+ }
+
+ private <T> T createMonitor(Class<T> monitorInterface, String bundleName) {
+ String className = monitorInterface.getName();
+ Logger logger = Logger.getLogger(className);
+ 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);
+ }
+
+ ResourceBundle bundle = locateBundle(monitorInterface, bundleName);
+
+ InvocationHandler handler = new LoggingHandler(logger, levels, bundle, formatters, defaultFormatter);
+ return monitorInterface
+ .cast(Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class<?>[]{monitorInterface}, handler));
+ }
+
+ private static <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);
+ }
+
+ private static final class LoggingHandler implements InvocationHandler {
+ private final Logger logger;
+ private final Map<String, Level> methodLevels;
+ private final ResourceBundle bundle;
+ private List<ExceptionFormatter> formatters;
+ private ExceptionFormatter defaultFormatter;
+
+ public LoggingHandler(Logger logger,
+ Map<String, Level> methodLevels,
+ ResourceBundle bundle,
+ List<ExceptionFormatter> formatters,
+ ExceptionFormatter defaultFormatter) {
+ this.logger = logger;
+ this.methodLevels = methodLevels;
+ this.bundle = bundle;
+ this.formatters = formatters;
+ this.defaultFormatter = defaultFormatter;
+ }
+
+ 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) {
+ Throwable e = (Throwable) o;
+ ExceptionFormatter formatter = null;
+ for (ExceptionFormatter candidate : formatters) {
+ if (candidate.canFormat(e.getClass())) {
+ formatter = candidate;
+ break;
+ }
+ }
+ StringWriter writer = new StringWriter();
+ PrintWriter pw = new PrintWriter(writer);
+ if (formatter != null) {
+ formatter.write(pw, e);
+ } else {
+ defaultFormatter.write(pw, e);
+ }
+ format(pw, e);
+ pw.close();
+ logRecord.setMessage(writer.toString());
+ break;
+ }
+ }
+ }
+ logRecord.setResourceBundle(bundle);
+ logger.log(logRecord);
+ }
+ return null;
+ }
+
+ private 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);
+ }
+ }
+
+ private 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 = null;
+ for (ExceptionFormatter candidate : formatters) {
+ if (candidate.canFormat(throwable.getClass())) {
+ formatter = candidate;
+ break;
+ }
+ }
+ if (formatter != null) {
+ formatter.write(pw, throwable);
+ } else {
+ defaultFormatter.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java
new file mode 100644
index 0000000000..8ba3053c2f
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.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.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;
+
+/**
+ * Implementation of a {@link MonitorFactory} that produces implementations that simply return.
+ *
+ * @version $Rev$ $Date$
+ */
+@EagerInit
+public class NullMonitorFactory implements MonitorFactory {
+ /**
+ * Singleton wire 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));
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java
new file mode 100644
index 0000000000..e80d5c7b00
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.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.policy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.apache.tuscany.spi.policy.PolicyBuilderRegistry;
+import org.apache.tuscany.spi.policy.SourcePolicyBuilder;
+import org.apache.tuscany.spi.policy.TargetPolicyBuilder;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * The default policy builder
+ *
+ * @version $Rev$ $Date$
+ */
+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);
+ }
+
+
+ public void buildSource(ReferenceDefinition referenceDefinition, OutboundWire wire) throws BuilderException {
+ for (List<SourcePolicyBuilder> builders : sourceBuilders) {
+ for (SourcePolicyBuilder builder : builders) {
+ builder.build(referenceDefinition, wire);
+ }
+ }
+ }
+
+ public void buildTarget(ServiceDefinition serviceDefinition, InboundWire wire) throws BuilderException {
+ for (List<TargetPolicyBuilder> builders : targetBuilders) {
+ for (TargetPolicyBuilder builder : builders) {
+ builder.build(serviceDefinition, wire);
+ }
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java
new file mode 100644
index 0000000000..77e3a6829f
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.apache.tuscany.core.databinding.xml.InputStream2Node;
+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.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ * 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) {
+ InvalidValueException ex =
+ new InvalidValueException(
+ "The 'source' cannot be resolved to a composite property");
+ ex.addContextName(source);
+ throw ex;
+ }
+ 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);
+ propValue.setValue(node);
+ Property<?> prop =
+ (Property<?>)componentDefinition.getImplementation().getComponentType()
+ .getProperties().get(propValue.getName());
+ propValue
+ .setValueFactory(new SimplePropertyObjectFactory(prop, propValue.getValue()));
+ } else {
+ InvalidValueException ex =
+ new InvalidValueException("The 'source' has an invalid value");
+ ex.addContextName(source);
+ throw ex;
+ }
+ } 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java
new file mode 100644
index 0000000000..acb1403228
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.apache.tuscany.core.databinding.xml.DOMDataBinding;
+import org.apache.tuscany.spi.ObjectCreationException;
+import org.apache.tuscany.spi.ObjectFactory;
+import org.apache.tuscany.spi.annotation.Autowire;
+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.idl.ElementInfo;
+import org.apache.tuscany.spi.idl.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.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.Scope;
+import org.osoa.sca.annotations.Service;
+import org.w3c.dom.Node;
+
+@Service(PropertyObjectFactory.class)
+@Scope("COMPOSITE")
+public class PropertyObjectFactoryImpl implements PropertyObjectFactory {
+ private DataBindingRegistry registry;
+ private Mediator mediator;
+
+ public PropertyObjectFactoryImpl() {
+ }
+
+ @Constructor({"registry", "mediator"})
+ public PropertyObjectFactoryImpl(@Autowire DataBindingRegistry registry, @Autowire 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 = new TypeInfo(property.getXmlType(), true, 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java
new file mode 100644
index 0000000000..b291eb8d96
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.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.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.idl.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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java
new file mode 100644
index 0000000000..9a91c9569d
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.URL;
+import javax.xml.stream.XMLInputFactory;
+
+import org.osoa.sca.CompositeContext;
+
+import org.apache.tuscany.core.bootstrap.Bootstrapper;
+import org.apache.tuscany.core.bootstrap.DefaultBootstrapper;
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+import org.apache.tuscany.core.monitor.NullMonitorFactory;
+import org.apache.tuscany.core.launcher.CompositeContextImpl;
+import org.apache.tuscany.host.MonitorFactory;
+import org.apache.tuscany.host.RuntimeInfo;
+import org.apache.tuscany.host.management.ManagementService;
+import org.apache.tuscany.host.runtime.InitializationException;
+import org.apache.tuscany.host.runtime.TuscanyRuntime;
+import org.apache.tuscany.spi.bootstrap.RuntimeComponent;
+import org.apache.tuscany.spi.bootstrap.ComponentNames;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.ComponentException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.ComponentRegistrationException;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.TargetResolutionException;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeImplementation;
+import org.apache.tuscany.spi.services.management.TuscanyManagementService;
+import org.apache.tuscany.spi.wire.WireService;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractRuntime implements TuscanyRuntime {
+ private final XMLInputFactory xmlFactory;
+ private URL systemScdl;
+ private String applicationName;
+ private URL applicationScdl;
+ private ClassLoader hostClassLoader;
+ private ClassLoader applicationClassLoader;
+ private RuntimeInfo runtimeInfo;
+ private MonitorFactory monitorFactory;
+ private ManagementService<?> managementService;
+
+ private RuntimeComponent runtime;
+ private CompositeComponent systemComponent;
+ private CompositeComponent tuscanySystem;
+ private Deployer deployer;
+ private WireService wireService;
+
+ protected AbstractRuntime() {
+ this(new NullMonitorFactory());
+ }
+
+ protected AbstractRuntime(MonitorFactory monitorFactory) {
+ this.monitorFactory = monitorFactory;
+ xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ }
+
+ 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 RuntimeInfo getRuntimeInfo() {
+ return runtimeInfo;
+ }
+
+ public void setRuntimeInfo(RuntimeInfo 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;
+ }
+
+ protected XMLInputFactory getXMLFactory() {
+ return xmlFactory;
+ }
+
+ protected RuntimeComponent getRuntime() {
+ return runtime;
+ }
+
+ protected CompositeComponent getSystemComponent() {
+ return systemComponent;
+ }
+
+ protected CompositeComponent getTuscanySystem() {
+ return tuscanySystem;
+ }
+
+ protected Deployer getDeployer() {
+ return deployer;
+ }
+
+ protected WireService getWireService() {
+ return wireService;
+ }
+
+ public void initialize() throws InitializationException {
+ Bootstrapper bootstrapper = createBootstrapper();
+ runtime = bootstrapper.createRuntime();
+ runtime.start();
+
+ systemComponent = runtime.getSystemComponent();
+ registerSystemComponents();
+ systemComponent.start();
+
+ // deploy the system scdl
+ try {
+ tuscanySystem = deploySystemScdl(bootstrapper.createDeployer(),
+ systemComponent,
+ ComponentNames.TUSCANY_SYSTEM,
+ getSystemScdl(),
+ getClass().getClassLoader());
+ } catch (LoaderException e) {
+ throw new InitializationException(e);
+ } catch (BuilderException e) {
+ throw new InitializationException(e);
+ } catch (ComponentException e) {
+ throw new InitializationException(e);
+ }
+ tuscanySystem.start();
+
+ this.deployer = locateDeployer();
+ this.wireService = locateWireService();
+ }
+
+ public void destroy() {
+ this.wireService = null;
+ this.deployer = null;
+ if (tuscanySystem != null) {
+ tuscanySystem.stop();
+ tuscanySystem = null;
+ }
+ if (systemComponent != null) {
+ systemComponent.stop();
+ systemComponent = null;
+ }
+ if (runtime != null) {
+ runtime.stop();
+ runtime = null;
+ }
+ }
+
+
+
+ protected Bootstrapper createBootstrapper() {
+ TuscanyManagementService tms = (TuscanyManagementService) getManagementService();
+ return new DefaultBootstrapper(getMonitorFactory(), xmlFactory, tms);
+ }
+
+ protected void registerSystemComponents() throws InitializationException {
+ try {
+ systemComponent.registerJavaObject(RuntimeInfo.COMPONENT_NAME, RuntimeInfo.class, runtimeInfo);
+ systemComponent.registerJavaObject("MonitorFactory", MonitorFactory.class, getMonitorFactory());
+ } catch (ComponentRegistrationException e) {
+ throw new InitializationException(e);
+ }
+ }
+
+ protected Deployer locateDeployer() throws InitializationException {
+ SCAObject deployerComponent = tuscanySystem.getSystemChild(ComponentNames.TUSCANY_DEPLOYER);
+ if (!(deployerComponent instanceof AtomicComponent)) {
+ throw new InitializationException("Deployer must be an atomic component");
+ }
+ try {
+ return (Deployer)((AtomicComponent)deployerComponent).getTargetInstance();
+ } catch (TargetResolutionException e) {
+ throw new InitializationException(e);
+ }
+ }
+
+ protected WireService locateWireService() throws InitializationException {
+ SCAObject wireServiceComponent = tuscanySystem.getSystemChild(ComponentNames.TUSCANY_WIRE_SERVICE);
+ if (!(wireServiceComponent instanceof AtomicComponent)) {
+ throw new InitializationException("WireService must be an atomic component");
+ }
+ try {
+ return (WireService)((AtomicComponent)wireServiceComponent).getTargetInstance();
+ } catch (TargetResolutionException e) {
+ throw new InitializationException(e);
+ }
+ }
+
+ protected CompositeComponent deploySystemScdl(Deployer deployer,
+ CompositeComponent parent,
+ String name,
+ URL systemScdl,
+ ClassLoader systemClassLoader)
+ throws LoaderException, BuilderException, ComponentException {
+
+ SystemCompositeImplementation impl = new SystemCompositeImplementation();
+ impl.setScdlLocation(systemScdl);
+ impl.setClassLoader(systemClassLoader);
+ ComponentDefinition<SystemCompositeImplementation> definition =
+ new ComponentDefinition<SystemCompositeImplementation>(name, impl);
+
+ return (CompositeComponent) deployer.deploy(parent, definition);
+ }
+
+ @Deprecated
+ public CompositeContext deployApplication(String name, URL scdlLocation, ClassLoader classLoader)
+ throws InitializationException {
+ try {
+ CompositeComponent application = deployApplicationScdl(getDeployer(),
+ getRuntime().getRootComponent(),
+ name,
+ scdlLocation,
+ classLoader);
+ application.start();
+ return new CompositeContextImpl(application, getWireService());
+ } catch (LoaderException ex) {
+ throw new InitializationException(ex);
+ } catch (BuilderException ex) {
+ throw new InitializationException(ex);
+ } catch (ComponentException ex) {
+ throw new InitializationException(ex);
+ }
+ }
+
+ protected CompositeComponent deployApplicationScdl(Deployer deployer,
+ CompositeComponent parent,
+ String name,
+ URL applicationScdl,
+ ClassLoader applicationClassLoader)
+ throws LoaderException, BuilderException, ComponentException {
+
+ CompositeImplementation impl = new CompositeImplementation();
+ impl.setScdlLocation(applicationScdl);
+ impl.setClassLoader(applicationClassLoader);
+ ComponentDefinition<CompositeImplementation> definition =
+ new ComponentDefinition<CompositeImplementation>(name, impl);
+
+ return (CompositeComponent) deployer.deploy(parent, definition);
+ }
+
+ public CompositeContext getContext() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java
new file mode 100644
index 0000000000..64fec4e246
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.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.services.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.host.deployment.ContributionService;
+import org.apache.tuscany.host.deployment.DeploymentException;
+import org.apache.tuscany.host.deployment.UnsupportedContentTypeException;
+import org.apache.tuscany.spi.deployer.ContributionProcessor;
+import org.apache.tuscany.spi.deployer.ContributionProcessorRegistry;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class ContributionServiceImpl implements ContributionService, ContributionProcessorRegistry {
+ private Map<String, ContributionProcessor> registry = new HashMap<String, ContributionProcessor>();
+
+ public void register(ContributionProcessor processor) {
+ registry.put(processor.getContentType(), processor);
+ }
+
+ public URI contribute(URL contribution) 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);
+ }
+
+ URLConnection connection = contribution.openConnection();
+ String contentType = connection.getContentType();
+ //todo try and figure out content type from the URL
+ if (contentType == null) {
+ throw new UnsupportedContentTypeException(null, contribution.toString());
+ }
+
+ InputStream is = connection.getInputStream();
+ try {
+ return contribute(source, is, contentType);
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ public URI contribute(URI source, InputStream contribution, String contentType)
+ throws DeploymentException, IOException {
+ if (contentType == null) {
+ throw new IllegalArgumentException("contentType was null");
+ }
+
+ ContributionProcessor processor = registry.get(contentType);
+ if (processor == null) {
+ throw new UnsupportedContentTypeException(contentType, source.toString());
+ }
+
+ return null;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java
new file mode 100644
index 0000000000..87f68340e2
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.bootstrap.RuntimeComponent;
+import org.apache.tuscany.spi.builder.Builder;
+import org.apache.tuscany.spi.builder.BuilderException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.ComponentRegistrationException;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.PrepareException;
+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 RuntimeComponent runtime;
+ private final Builder builder;
+ private final Loader loader;
+ private final XMLInputFactory xmlFactory;
+
+ public XMLChangeSetHandler(RuntimeComponent runtime, Loader loader, Builder builder) {
+ this.runtime = runtime;
+ 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, xmlFactory, null, null);
+ CompositeComponent parent = runtime.getRootComponent();
+ try {
+ ComponentDefinition<?> componentDefinition =
+ (ComponentDefinition<?>) loader.load(parent, null, xmlReader, deploymentContext);
+ Component component = builder.build(parent, componentDefinition, deploymentContext);
+ component.prepare();
+ parent.register(component);
+ } catch (LoaderException e) {
+ // FIXME throw something appropriate
+ throw new AssertionError("FIXME");
+ } catch (BuilderException e) {
+ // FIXME throw something appropriate
+ throw new AssertionError("FIXME");
+ } catch (PrepareException e) {
+ // FIXME throw something appropriate
+ throw new AssertionError("FIXME");
+ } catch (ComponentRegistrationException e) {
+ // FIXME throw something appropriate
+ throw new AssertionError("FIXME");
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java
new file mode 100644
index 0000000000..cc3339e2b7
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.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.services.extension;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.ComponentException;
+import org.apache.tuscany.spi.deployer.CompositeClassLoader;
+import org.apache.tuscany.spi.deployer.Deployer;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.builder.BuilderException;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class AbstractExtensionDeployer {
+ protected Deployer deployer;
+ protected CompositeComponent parent;
+
+ @Autowire
+ public void setDeployer(Deployer deployer) {
+ this.deployer = deployer;
+ }
+
+ @Autowire
+ public void setParent(CompositeComponent parent) {
+ this.parent = parent;
+ }
+
+ 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) {
+ // 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);
+ ComponentDefinition<SystemCompositeImplementation> definition =
+ new ComponentDefinition<SystemCompositeImplementation>(name, 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 = null;
+ 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 (LoaderException e) {
+ // FIXME handle the exception
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java
new file mode 100644
index 0000000000..b1a0b67001
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.getCanonicalName(), 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.getCanonicalName(), id);
+ }
+ Record record = map.get(id);
+ if (record == null) {
+ throw new StoreWriteException("Record not found", owner.getCanonicalName(), 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.getCanonicalName(), id);
+ }
+ if (map.remove(id) == null) {
+ throw new StoreWriteException("Owner not found", owner.getCanonicalName(), 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java
new file mode 100644
index 0000000000..8fa8000477
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.Scope;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java
new file mode 100644
index 0000000000..a8c57db9d1
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.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.util;
+
+import java.io.File;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.net.URLClassLoader;
+
+/**
+ * Functions to create & manipulate classloaders.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+
+public final class ClassLoaderHelper {
+ /**
+ * Hide constructor
+ */
+ private ClassLoaderHelper() {
+ }
+
+ /**
+ * Create a classloader for the supplied classpath.
+ *
+ * @param path a list of file/directory names separated by the platform path separator
+ * @param parent the parent for the new classloader
+ * @return a classloader that will load classes from the supplied path
+ */
+ public static ClassLoader createClassLoader(ClassLoader parent, String path) {
+ String[] files = path.split(File.pathSeparator);
+ return createClassLoader(parent, files);
+ }
+
+ /**
+ * Create a classloader for a classpath supplied as individual file names.
+ *
+ * @param files a list of file/directory names
+ * @param parent the parent for the new classloader
+ * @return a classloader that will load classes from the supplied path
+ */
+ public static ClassLoader createClassLoader(ClassLoader parent, String[] files) {
+ URL[] urls = new URL[files.length];
+ for (int i = 0; i < files.length; i++) {
+ try {
+ File file = new File(files[i]);
+ urls[i] = file.toURI().toURL();
+ } catch (MalformedURLException e) {
+ // just ignore this value
+ continue;
+ }
+ }
+
+ return new URLClassLoader(urls, parent);
+ }
+
+ /**
+ * Create a classloader for a classpath supplied as a list of files.
+ *
+ * @param files a list of files
+ * @param parent the parent for the new classloader
+ * @return a classloader that will load classes from the supplied path
+ */
+ public static ClassLoader createClassLoader(ClassLoader parent, File[] files) {
+ URL[] urls = new URL[files.length];
+ for (int i = 0; i < files.length; i++) {
+ try {
+ File file = files[i];
+ urls[i] = file.toURI().toURL();
+ } catch (MalformedURLException e) {
+
+ continue;
+ }
+ }
+ return new URLClassLoader(urls, parent);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java
new file mode 100644
index 0000000000..c1766fbb6f
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.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.wire;
+
+import org.apache.tuscany.spi.wire.Interceptor;
+
+/**
+ * Responsible for bridging an outbound to an inbound invocation chain associated with a source and target respectively
+ *
+ * @version $Rev$ $Date$
+ */
+public interface BridgingInterceptor extends Interceptor {
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java
new file mode 100644
index 0000000000..06f0e62f70
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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 outbound side 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java
new file mode 100644
index 0000000000..45b580d419
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.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.wire;
+
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+
+/**
+ * Contains a target-side invocation chain
+ *
+ * @version $Rev$ $Date$
+ */
+public class InboundInvocationChainImpl extends InvocationChainImpl implements InboundInvocationChain {
+
+ /**
+ * Creates an new target-side chain for the given operation
+ */
+ public InboundInvocationChainImpl(Operation operation) {
+ super(operation);
+ }
+
+ public void prepare() {
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java
new file mode 100644
index 0000000000..b529cafbb6
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.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.wire;
+
+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.SCAObject;
+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.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * Default implementation of an inbound wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class InboundWireImpl implements InboundWire {
+ private QName bindingType = LOCAL_BINDING;
+ private String serviceName;
+ private ServiceContract serviceContract;
+ private OutboundWire targetWire;
+ private String callbackReferenceName;
+ private Map<Operation<?>, InboundInvocationChain> chains = new HashMap<Operation<?>, InboundInvocationChain>();
+ private Map<Object, Map<Operation<?>, OutboundInvocationChain>> callbackSourceChainMaps =
+ new HashMap<Object, Map<Operation<?>, OutboundInvocationChain>>();
+ private SCAObject container;
+ private AtomicComponent targetComponent;
+ private boolean optimizable;
+
+
+ /**
+ * Creates a local inbound wire
+ */
+ public InboundWireImpl() {
+ }
+
+
+ /**
+ * Creates an inbound wire for the given binding type
+ *
+ * @param bindingType the binding type
+ */
+ public InboundWireImpl(QName bindingType) {
+ this.bindingType = bindingType;
+ }
+
+ public QName getBindingType() {
+ return bindingType;
+ }
+
+ public Object getTargetService() throws TargetResolutionException {
+ // JFM fixme hack
+ if (targetWire == null && targetComponent != null) {
+ return targetComponent.getTargetInstance();
+ }
+ assert targetWire != null;
+ // optimized, no interceptors or handlers on either end
+ return targetWire.getTargetService();
+ }
+
+ public ServiceContract getServiceContract() {
+ return serviceContract;
+ }
+
+ public void setServiceContract(ServiceContract serviceContract) {
+ this.serviceContract = serviceContract;
+ }
+
+ public void addInterface(Class claz) {
+ throw new UnsupportedOperationException("Additional proxy interfaces not yet supported");
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public Map<Operation<?>, InboundInvocationChain> getInvocationChains() {
+ return chains;
+ }
+
+ public void addInvocationChains(Map<Operation<?>, InboundInvocationChain> chains) {
+ this.chains.putAll(chains);
+ }
+
+ public void addInvocationChain(Operation<?> operation, InboundInvocationChain chain) {
+ chains.put(operation, chain);
+ }
+
+ public Map<Operation<?>, OutboundInvocationChain> getSourceCallbackInvocationChains(Object targetAddr) {
+ return callbackSourceChainMaps.get(targetAddr);
+ }
+
+ public void addSourceCallbackInvocationChains(Object targetAddr,
+ Map<Operation<?>, OutboundInvocationChain> chains) {
+ callbackSourceChainMaps.put(targetAddr, chains);
+ }
+
+ public void addSourceCallbackInvocationChain(Object targetAddr,
+ Operation operation,
+ OutboundInvocationChain chain) {
+ Map<Operation<?>, OutboundInvocationChain> chains = callbackSourceChainMaps.get(targetAddr);
+ if (chains == null) {
+ chains = new HashMap<Operation<?>, OutboundInvocationChain>();
+ callbackSourceChainMaps.put(targetAddr, chains);
+ }
+ chains.put(operation, chain);
+ }
+
+ public void setTargetWire(OutboundWire wire) {
+ targetWire = wire;
+ }
+
+ public String getCallbackReferenceName() {
+ return callbackReferenceName;
+ }
+
+ public void setCallbackReferenceName(String callbackReferenceName) {
+ this.callbackReferenceName = callbackReferenceName;
+ }
+
+ public boolean isOptimizable() {
+ return optimizable;
+ }
+
+ public void setOptimizable(boolean optimizable) {
+ this.optimizable = optimizable;
+ }
+
+ public SCAObject getContainer() {
+ return container;
+ }
+
+ public void setContainer(SCAObject container) {
+ if (container instanceof AtomicComponent) {
+ targetComponent = (AtomicComponent) container;
+ }
+ this.container = container;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java
new file mode 100644
index 0000000000..92da622d11
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.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 java.io.PrintWriter;
+
+import org.osoa.sca.annotations.Destroy;
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+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(@Autowire 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");
+
+ }
+ e.appendContextStack(writer);
+ return writer;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java
new file mode 100644
index 0000000000..d93426af4c
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.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.wire;
+
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.InvocationChain;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * Contains functionality common to source- and target- side invocation chains
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class InvocationChainImpl implements InvocationChain {
+ protected Operation operation;
+ protected TargetInvoker targetInvoker;
+ protected Interceptor interceptorChainHead;
+ protected Interceptor interceptorChainTail;
+
+
+ // the pointer to a bridged target head interceptor or null if the target has no interceptors
+ protected Interceptor targetInterceptorChainHead;
+
+ public InvocationChainImpl(Operation operation) {
+ assert operation != null : "No operation type specified";
+ 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;
+ }
+
+ public void setTargetInterceptor(Interceptor interceptor) {
+ targetInterceptorChainHead = interceptor;
+ }
+
+ public Interceptor getTargetInterceptor() {
+ return targetInterceptorChainHead;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java
new file mode 100644
index 0000000000..a2cd71cafe
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.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.wire;
+
+import org.apache.tuscany.spi.component.TargetResolutionException;
+
+/**
+ * A specialized wire that points back to its target container. Used to autowire to parent composites
+ *
+ * @version $Rev$ $Date$
+ */
+public class LoopBackWire extends InboundWireImpl {
+
+ public Object getTargetService() throws TargetResolutionException {
+ return getContainer();
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java b/sca-java-1.x/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java
new file mode 100644
index 0000000000..225cab79bc
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.LinkedList;
+
+import org.osoa.sca.CompositeContext;
+import org.osoa.sca.CurrentCompositeContext;
+import org.osoa.sca.ServiceRuntimeException;
+
+import org.apache.tuscany.spi.component.WorkContext;
+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;
+import org.apache.tuscany.spi.model.Scope;
+
+/**
+ * Bridges interceptors in a non-blocking fashion between an {@link org.apache.tuscany.spi.wire.InboundInvocationChain}
+ * and an {@link org.apache.tuscany.spi.wire.OutboundInvocationChain} by using a {@link
+ * org.apache.tuscany.spi.component.WorkContext}.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class NonBlockingBridgingInterceptor implements BridgingInterceptor {
+
+ private static final Message RESPONSE = new ImmutableMessage();
+
+ private WorkScheduler workScheduler;
+ private WorkContext workContext;
+ private Interceptor next;
+
+ public NonBlockingBridgingInterceptor(WorkScheduler workScheduler, WorkContext workContext) {
+ this.workScheduler = workScheduler;
+ this.workContext = workContext;
+ }
+
+ public NonBlockingBridgingInterceptor(WorkScheduler workScheduler, WorkContext workContext, Interceptor next) {
+ this.workScheduler = workScheduler;
+ this.workContext = workContext;
+ this.next = next;
+ }
+
+ public Message invoke(final Message msg) {
+ final CompositeContext currentContext = CurrentCompositeContext.getContext();
+ // 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.setCurrentCorrelationId(null);
+ // if we got a conversation id, transfer it to new thread
+ if (conversationID != null) {
+ workContext.setIdentifier(Scope.CONVERSATION, conversationID);
+ }
+ CompositeContext oldContext = CurrentCompositeContext.setContext(currentContext);
+ try {
+ next.invoke(msg);
+ } catch (Exception e) {
+ // REVIEW uncomment when it is available
+ // monitor.executionError(e);
+ e.printStackTrace();
+ } finally {
+ CurrentCompositeContext.setContext(oldContext);
+ }
+ }
+ });
+ } 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 Object getFromAddress() {
+ return null;
+ }
+
+ public void setFromAddress(Object fromAddress) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object popFromAddress() {
+ return null;
+ }
+
+ public void pushFromAddress(Object fromAddress) {
+ throw new UnsupportedOperationException();
+ }
+
+ public LinkedList<Object> getCallbackRoutingChain() {
+ return null;
+ }
+
+ public void setCallbackRoutingChain(LinkedList<Object> fromAddresses) {
+ 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/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java
new file mode 100644
index 0000000000..4a4b268201
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.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.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.OutboundWire;
+
+/**
+ * Returns a target instance directly from a wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class OptimizedWireObjectFactory implements ObjectFactory {
+
+ private OutboundWire wire;
+
+ public OptimizedWireObjectFactory(OutboundWire factory) {
+ this.wire = factory;
+ }
+
+ public Object getInstance() throws ObjectCreationException {
+ try {
+ return wire.getTargetService();
+ } catch (TargetResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java
new file mode 100644
index 0000000000..a9d83cb7a0
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.wire;
+
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+
+/**
+ * Contains a outgoing invocation pipeline for a service operation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class OutboundInvocationChainImpl extends InvocationChainImpl implements OutboundInvocationChain {
+
+ /**
+ * Creates an new outbound chain
+ */
+ public OutboundInvocationChainImpl(Operation operation) {
+ super(operation);
+ }
+
+ public void prepare() {
+ if (interceptorChainHead != null) {
+ if (targetInterceptorChainHead != null) {
+ // Connect source interceptor chain directly to target interceptor chain
+ interceptorChainTail.setNext(targetInterceptorChainHead);
+ }
+ } else {
+ // no source interceptor chain or source handlers, connect to target interceptor chain or channel
+ if (targetInterceptorChainHead != null) {
+ interceptorChainHead = targetInterceptorChainHead;
+ interceptorChainTail = targetInterceptorChainHead;
+ }
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java
new file mode 100644
index 0000000000..bad92ffe1e
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.HashMap;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.component.SCAObject;
+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.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * Default implementation of an outbound wire
+ *
+ * @version $Rev$ $Date$
+ */
+public class OutboundWireImpl implements OutboundWire {
+ private QName bindingType = LOCAL_BINDING;
+ private ServiceContract serviceContract;
+ private Class<?>[] callbackInterfaces;
+ private Map<Operation<?>, OutboundInvocationChain> chains = new HashMap<Operation<?>, OutboundInvocationChain>();
+ private Map<Operation<?>, InboundInvocationChain> callbackTargetChains =
+ new HashMap<Operation<?>, InboundInvocationChain>();
+ private String referenceName;
+ private QualifiedName targetName;
+ private InboundWire targetWire;
+ private SCAObject container;
+ private boolean autowire;
+ private boolean optimizable;
+
+ /**
+ * Creates a local outbound wire
+ */
+ public OutboundWireImpl() {
+ }
+
+ /**
+ * Creates an outbound wire for the given binding type
+ *
+ * @param bindingType the binding type
+ */
+ public OutboundWireImpl(QName bindingType) {
+ this.bindingType = bindingType;
+ }
+
+ public void setOptimizable(boolean optimizable) {
+ this.optimizable = optimizable;
+ }
+
+ public QName getBindingType() {
+ return bindingType;
+ }
+
+ public Object getTargetService() throws TargetResolutionException {
+ if (targetWire == null) {
+ return null;
+ }
+ // optimized, no interceptors or handlers on either end
+ return targetWire.getTargetService();
+ }
+
+ public ServiceContract getServiceContract() {
+ return serviceContract;
+ }
+
+ public void setServiceContract(ServiceContract serviceContract) {
+ this.serviceContract = serviceContract;
+ }
+
+ public void addInterface(Class<?> claz) {
+ throw new UnsupportedOperationException("Additional proxy interfaces not yet supported");
+ }
+
+ public void setCallbackInterface(Class<?> interfaze) {
+ callbackInterfaces = new Class[]{interfaze};
+ }
+
+ public Class<?> getCallbackInterface() {
+ return callbackInterfaces[0];
+ }
+
+ public void addCallbackInterface(Class<?> claz) {
+ throw new UnsupportedOperationException("Additional callback interfaces not yet supported");
+ }
+
+ public Class[] getImplementedCallbackInterfaces() {
+ return callbackInterfaces;
+ }
+
+ public void setTargetWire(InboundWire wire) {
+ this.targetWire = wire;
+ }
+
+ public Map<Operation<?>, OutboundInvocationChain> getInvocationChains() {
+ return chains;
+ }
+
+ public void addInvocationChains(Map<Operation<?>, OutboundInvocationChain> chains) {
+ this.chains.putAll(chains);
+ }
+
+ public void addInvocationChain(Operation<?> operation, OutboundInvocationChain chain) {
+ chains.put(operation, chain);
+ }
+
+ public Map<Operation<?>, InboundInvocationChain> getTargetCallbackInvocationChains() {
+ return callbackTargetChains;
+ }
+
+ public void addTargetCallbackInvocationChains(Map<Operation<?>, InboundInvocationChain> chains) {
+ callbackTargetChains.putAll(chains);
+ }
+
+ public void addTargetCallbackInvocationChain(Operation operation, InboundInvocationChain chain) {
+ callbackTargetChains.put(operation, chain);
+ }
+
+ public String getReferenceName() {
+ return referenceName;
+ }
+
+ public void setReferenceName(String referenceName) {
+ this.referenceName = referenceName;
+ }
+
+ public QualifiedName getTargetName() {
+ return targetName;
+ }
+
+ public void setTargetName(QualifiedName targetName) {
+ this.targetName = targetName;
+ }
+
+ public boolean isAutowire() {
+ return autowire;
+ }
+
+ public void setAutowire(boolean autowire) {
+ this.autowire = autowire;
+ }
+
+ public boolean isOptimizable() {
+ return optimizable;
+ }
+
+ public SCAObject getContainer() {
+ return container;
+ }
+
+ public void setContainer(SCAObject container) {
+ this.container = container;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java
new file mode 100644
index 0000000000..f09bda400a
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.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.wire;
+
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.Message;
+
+/**
+ * Synchronously bridges interceptors between an {@link org.apache.tuscany.spi.wire.InboundInvocationChain} and an
+ * {@link org.apache.tuscany.spi.wire.OutboundInvocationChain}.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SynchronousBridgingInterceptor implements BridgingInterceptor {
+ private Interceptor next;
+
+ public SynchronousBridgingInterceptor() {
+ }
+
+ public SynchronousBridgingInterceptor(Interceptor next) {
+ this.next = next;
+ }
+
+ public Message invoke(Message msg) {
+ return next.invoke(msg);
+ }
+
+ public Interceptor getNext() {
+ return next;
+ }
+
+ public void setNext(Interceptor next) {
+ this.next = next;
+ }
+
+ public boolean isOptimizable() {
+ return true;
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java
new file mode 100644
index 0000000000..c04869e8f5
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/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.OutboundChainHolder;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.WireService;
+
+/**
+ * Uses a wire to return an object instance
+ *
+ * @version $Rev$ $Date$
+ */
+public class WireObjectFactory<T> implements ObjectFactory<T> {
+ private Class<T> interfaze;
+ private OutboundWire wire;
+ private WireService wireService;
+ // the cache of proxy interface method to operation mappings
+ private Map<Method, OutboundChainHolder> mappings;
+ private boolean optimizable;
+
+ /**
+ * Constructor.
+ *
+ * @param interfaze the interface to inject on the client
+ * @param wire the backing wire
+ * @param wireService the wire service to create the proxy
+ * @throws NoMethodForOperationException
+ */
+ public WireObjectFactory(Class<T> interfaze, OutboundWire wire, WireService wireService)
+ throws NoMethodForOperationException {
+ this.interfaze = interfaze;
+ this.wire = wire;
+ this.wireService = wireService;
+ this.mappings = WireUtils.createInterfaceToWireMapping(interfaze, wire);
+ }
+
+ public T getInstance() throws ObjectCreationException {
+ // note optimization must be done lazily as wire object factories are created during the build phase prior
+ // to the outbound and inbound wires being connected
+ if ((optimizable
+ || wire.isOptimizable())
+ && wire.getServiceContract().getInterfaceClass() != null
+ && interfaze.isAssignableFrom(wire.getServiceContract().getInterfaceClass())) {
+ optimizable = true;
+ try {
+ return interfaze.cast(wire.getTargetService());
+ } catch (TargetResolutionException e) {
+ throw new ObjectCreationException(e);
+ }
+ }
+ // clone the cached mappings
+ Map<Method, OutboundChainHolder> newChains = new HashMap<Method, OutboundChainHolder>(mappings.size());
+ for (Map.Entry<Method, OutboundChainHolder> entry : mappings.entrySet()) {
+ newChains.put(entry.getKey(), entry.getValue().clone());
+ }
+ return interfaze.cast(wireService.createProxy(interfaze, wire, newChains));
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java
new file mode 100644
index 0000000000..460a6a40a8
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.Map;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.component.AtomicComponent;
+import org.apache.tuscany.spi.component.ReferenceBinding;
+import org.apache.tuscany.spi.component.ServiceBinding;
+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.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.ServiceContract;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+import org.apache.tuscany.spi.policy.PolicyBuilderRegistry;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.IncompatibleServiceContractException;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.WireService;
+
+import org.apache.tuscany.core.binding.local.LocalReferenceBinding;
+
+/**
+ * Base class for wire service extensions
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class WireServiceExtension implements WireService {
+ protected PolicyBuilderRegistry policyRegistry;
+ protected WorkContext context;
+
+ protected WireServiceExtension(WorkContext context, PolicyBuilderRegistry policyRegistry) {
+ this.policyRegistry = policyRegistry;
+ this.context = context;
+ }
+
+ public OutboundInvocationChain createOutboundChain(Operation<?> operation) {
+ return new OutboundInvocationChainImpl(operation);
+ }
+
+ public InboundInvocationChain createInboundChain(Operation<?> operation) {
+ return new InboundInvocationChainImpl(operation);
+ }
+
+ public InboundWire createWire(ServiceDefinition service) {
+ InboundWire wire = new InboundWireImpl();
+ ServiceContract<?> contract = service.getServiceContract();
+ wire.setServiceContract(contract);
+ wire.setServiceName(service.getName());
+ for (Operation<?> operation : contract.getOperations().values()) {
+ InboundInvocationChain chain = createInboundChain(operation);
+ // TODO handle policy
+ chain.addInterceptor(new InvokerInterceptor());
+ wire.addInvocationChain(operation, chain);
+ }
+ if (contract.getCallbackName() != null) {
+ wire.setCallbackReferenceName(service.getCallbackReferenceName());
+ }
+ return wire;
+ }
+
+ public void createWires(AtomicComponent component, ComponentDefinition<?> definition) {
+ Implementation<?> implementation = definition.getImplementation();
+ ComponentType<?, ?, ?> componentType = implementation.getComponentType();
+ // create incoming service wires
+ for (ServiceDefinition service : componentType.getServices().values()) {
+ InboundWire wire = createWire(service);
+ wire.setContainer(component);
+ component.addInboundWire(wire);
+ }
+ // create outgoing reference wires
+ for (ReferenceTarget referenceTarget : definition.getReferenceTargets().values()) {
+ Map<String, ? extends ReferenceDefinition> references = componentType.getReferences();
+ ReferenceDefinition mappedReference = references.get(referenceTarget.getReferenceName());
+ assert mappedReference != null;
+ OutboundWire wire = createWire(referenceTarget, mappedReference);
+ wire.setContainer(component);
+ component.addOutboundWire(wire);
+ }
+ }
+
+ public void createWires(ReferenceBinding referenceBinding, ServiceContract<?> contract, QualifiedName targetName) {
+ InboundWire inboundWire = new InboundWireImpl(referenceBinding.getBindingType());
+ inboundWire.setServiceContract(contract);
+ inboundWire.setContainer(referenceBinding);
+ for (Operation<?> operation : contract.getOperations().values()) {
+ InboundInvocationChain chain = createInboundChain(operation);
+ inboundWire.addInvocationChain(operation, chain);
+ }
+ OutboundWire outboundWire = new OutboundWireImpl(referenceBinding.getBindingType());
+ outboundWire.setTargetName(targetName);
+
+ // [rfeng] Check if the Reference has the binding contract
+ ServiceContract<?> bindingContract = referenceBinding.getBindingServiceContract();
+ if (bindingContract == null) {
+ bindingContract = contract;
+ }
+ outboundWire.setServiceContract(bindingContract);
+ outboundWire.setContainer(referenceBinding);
+ for (Operation<?> operation : bindingContract.getOperations().values()) {
+ OutboundInvocationChain chain = createOutboundChain(operation);
+ if (referenceBinding instanceof LocalReferenceBinding) {
+ // Not ideal but the local binding case is special as its inbound and outbound wires are connected
+ // before the outbound wire is connected to the reference target. This requires the binding outbound
+ // chain to have an interceptor to connect to from the binding inbound chain. This outbound
+ // interceptor will then be bridged to the head target interceptor
+ chain.addInterceptor(new SynchronousBridgingInterceptor());
+ } else {
+ chain.addInterceptor(new InvokerInterceptor());
+ }
+ outboundWire.addInvocationChain(operation, chain);
+ }
+ // Add target callback chain to outbound wire
+ if (contract.getCallbackName() != null) {
+ outboundWire.setCallbackInterface(contract.getCallbackClass());
+ for (Operation<?> operation : contract.getCallbackOperations().values()) {
+ InboundInvocationChain callbackTargetChain = createInboundChain(operation);
+ // TODO handle policy
+ callbackTargetChain.addInterceptor(new InvokerInterceptor());
+ outboundWire.addTargetCallbackInvocationChain(operation, callbackTargetChain);
+ }
+ }
+ referenceBinding.setInboundWire(inboundWire);
+ referenceBinding.setOutboundWire(outboundWire);
+ }
+
+ public void createWires(ServiceBinding serviceBinding, ServiceContract<?> contract, String targetName) {
+ InboundWire inboundWire = new InboundWireImpl(serviceBinding.getBindingType());
+ // [rfeng] Check if the Reference has the serviceBinding contract
+ ServiceContract<?> bindingContract = serviceBinding.getBindingServiceContract();
+ if (bindingContract == null) {
+ bindingContract = contract;
+ }
+ inboundWire.setServiceContract(bindingContract);
+ inboundWire.setContainer(serviceBinding);
+ for (Operation<?> operation : bindingContract.getOperations().values()) {
+ InboundInvocationChain inboundChain = createInboundChain(operation);
+ inboundChain.addInterceptor(new SynchronousBridgingInterceptor());
+ inboundWire.addInvocationChain(operation, inboundChain);
+ }
+
+ OutboundWire outboundWire = new OutboundWireImpl(serviceBinding.getBindingType());
+ outboundWire.setServiceContract(contract);
+ outboundWire.setTargetName(new QualifiedName(targetName));
+ outboundWire.setContainer(serviceBinding);
+
+ for (Operation<?> operation : contract.getOperations().values()) {
+ OutboundInvocationChain outboundChain = createOutboundChain(operation);
+ outboundWire.addInvocationChain(operation, outboundChain);
+ }
+
+ // Add target callback chain to outbound wire
+ if (contract.getCallbackName() != null) {
+ outboundWire.setCallbackInterface(contract.getCallbackClass());
+ for (Operation<?> operation : contract.getCallbackOperations().values()) {
+ InboundInvocationChain callbackTargetChain = createInboundChain(operation);
+ // TODO handle policy
+ callbackTargetChain.addInterceptor(new InvokerInterceptor());
+ outboundWire.addTargetCallbackInvocationChain(operation, callbackTargetChain);
+ }
+ }
+ serviceBinding.setInboundWire(inboundWire);
+ serviceBinding.setOutboundWire(outboundWire);
+ }
+
+ /**
+ * Compares two operations for wiring compatibility as defined by the SCA assembly specification, namely: <p/> <ol>
+ * <li>compatibility for the individual method is defined as compatibility of the signature, that is method name,
+ * input types, and output types MUST BE the same. <li>the order of the input and output types also MUST BE the
+ * same. <li>the set of Faults and Exceptions expected by the source MUST BE the same or be a superset of those
+ * specified by the service. </ol>
+ *
+ * @param source the source contract to compare
+ * @param target the target contract to compare
+ * @throws org.apache.tuscany.spi.wire.IncompatibleServiceContractException
+ * if the two contracts don't match
+ */
+ public void checkCompatibility(ServiceContract<?> source, ServiceContract<?> target, boolean ignoreCallback)
+ throws IncompatibleServiceContractException {
+ if (source == target) {
+ // Shortcut for performance
+ return;
+ }
+ if (source.isRemotable() != target.isRemotable()) {
+ throw new IncompatibleServiceContractException("Remotable settings do not match", source, target);
+ }
+ if (source.getInteractionScope() != target.getInteractionScope()) {
+ throw new IncompatibleServiceContractException("Interaction scopes settings do not match", source, target);
+ }
+
+ for (Operation<?> operation : source.getOperations().values()) {
+ Operation<?> targetOperation = target.getOperations().get(operation.getName());
+ if (targetOperation == null) {
+ throw new IncompatibleServiceContractException("Operation not found on target", source, target);
+ }
+ if (!operation.equals(targetOperation)) {
+ throw new IncompatibleServiceContractException("Target operations are not compatible", source, target);
+ }
+ }
+
+ if (ignoreCallback) {
+ return;
+ }
+
+ for (Operation<?> operation : source.getCallbackOperations().values()) {
+ Operation<?> targetOperation = target.getCallbackOperations().get(operation.getName());
+ if (targetOperation == null) {
+ throw new IncompatibleServiceContractException("Callback operation not found on target",
+ source,
+ target,
+ null,
+ targetOperation);
+ }
+ if (!operation.equals(targetOperation)) {
+ throw new IncompatibleServiceContractException("Target callback operation is not compatible",
+ source,
+ target,
+ operation,
+ targetOperation);
+ }
+ }
+ }
+
+ /**
+ * Creates a wire for flowing outbound invocations from a reference
+ *
+ * @param target the reference definition
+ * @param definition the reference target configuration
+ * @return the wire the outbound wire
+ */
+ protected OutboundWire createWire(ReferenceTarget target, ReferenceDefinition definition) {
+ if (!definition.isAutowire() && target.getTargets().size() != 1) {
+ //TODO multiplicity
+ throw new UnsupportedOperationException();
+ }
+ ServiceContract<?> contract = definition.getServiceContract();
+ OutboundWire wire = new OutboundWireImpl();
+ if (!definition.isAutowire()) {
+ QualifiedName qName = new QualifiedName(target.getTargets().get(0).toString());
+ wire.setTargetName(qName);
+ } else {
+ wire.setAutowire(true);
+ }
+ wire.setServiceContract(contract);
+ wire.setReferenceName(target.getReferenceName());
+ for (Operation<?> operation : contract.getOperations().values()) {
+ //TODO handle policy
+ OutboundInvocationChain chain = createOutboundChain(operation);
+ wire.addInvocationChain(operation, chain);
+
+ }
+ if (contract.getCallbackName() != null) {
+ wire.setCallbackInterface(contract.getCallbackClass());
+ for (Operation<?> operation : contract.getCallbackOperations().values()) {
+ InboundInvocationChain callbackTargetChain = createInboundChain(operation);
+ // TODO handle policy
+ callbackTargetChain.addInterceptor(new InvokerInterceptor());
+ wire.addTargetCallbackInvocationChain(operation, callbackTargetChain);
+ }
+ }
+ return wire;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java
new file mode 100644
index 0000000000..73aa34e6bb
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.component.Component;
+import org.apache.tuscany.spi.component.SCAObject;
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.OutboundChainHolder;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+
+/**
+ * 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, InboundInvocationChain> createInboundMapping(InboundWire wire, Method[] methods)
+ throws NoMethodForOperationException {
+ Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>();
+ for (Map.Entry<Operation<?>, InboundInvocationChain> entry : wire.getInvocationChains().entrySet()) {
+ Operation<?> operation = entry.getKey();
+ InboundInvocationChain 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, OutboundChainHolder> createInterfaceToWireMapping(Class<?> interfaze, OutboundWire wire)
+ throws NoMethodForOperationException {
+ Map<Operation<?>, OutboundInvocationChain> invocationChains = wire.getInvocationChains();
+ Map<Method, OutboundChainHolder> chains = new HashMap<Method, OutboundChainHolder>(invocationChains.size());
+ Method[] methods = interfaze.getMethods();
+ for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : invocationChains.entrySet()) {
+ Operation operation = entry.getKey();
+ Method method = findMethod(operation, methods);
+ if (method == null) {
+ throw new NoMethodForOperationException(operation.getName());
+ }
+ chains.put(method, new OutboundChainHolder(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(OutboundWire wire) {
+ for (OutboundInvocationChain 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.getTargetCallbackInvocationChains().isEmpty();
+ }
+
+ /**
+ * 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(InboundWire wire) {
+ SCAObject container = wire.getContainer();
+ if (!(container instanceof Component) || !((Component) container).isOptimizable()) {
+ return false;
+ }
+ for (InboundInvocationChain chain : wire.getInvocationChains().values()) {
+ if (chain.getHeadInterceptor() != null) {
+ Interceptor current = chain.getHeadInterceptor();
+ while (current != null) {
+ if (!current.isOptimizable()) {
+ return false;
+ }
+ current = current.getNext();
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java
new file mode 100644
index 0000000000..741ef21794
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.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.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.util.LinkedList;
+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.AbstractOutboundInvocationHandler;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.WireInvocationHandler;
+
+
+/**
+ * Responsible for invoking on an outbound wire associated with a callback. The handler retrieves the correct outbound
+ * callback wire from the work context.
+ * <p/>
+ * TODO cache target invoker
+ *
+ * @version $Rev$ $Date$
+ */
+public class JDKCallbackInvocationHandler extends AbstractOutboundInvocationHandler
+ implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable {
+ private transient WorkContext context;
+ private transient InboundWire wire;
+ private String serviceName;
+
+ /**
+ * Constructor used for deserialization only
+ */
+ public JDKCallbackInvocationHandler() {
+ }
+
+ public JDKCallbackInvocationHandler(InboundWire wire, WorkContext context) {
+ this.context = context;
+ this.wire = wire;
+ this.serviceName = wire.getServiceName();
+ }
+
+ @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
+ }
+ Object correlationId = context.getCurrentCorrelationId();
+ context.setCurrentCorrelationId(null);
+ LinkedList<Object> callbackRoutingChain = (LinkedList<Object>) context.getCurrentCallbackRoutingChain().clone();
+ if (callbackRoutingChain == null) {
+ throw new AssertionError("Missing stack of from addresses");
+ }
+ Object targetAddress = callbackRoutingChain.removeFirst();
+ if (targetAddress == null) {
+ throw new AssertionError("Popped a null from address from stack");
+ }
+ //TODO optimize as this is slow in local invocations
+ Map<Operation<?>, OutboundInvocationChain> sourceCallbackInvocationChains =
+ wire.getSourceCallbackInvocationChains(targetAddress);
+ Operation operation = findOperation(method, sourceCallbackInvocationChains.keySet());
+ OutboundInvocationChain chain = sourceCallbackInvocationChains.get(operation);
+ TargetInvoker invoker = chain.getTargetInvoker();
+
+ try {
+ return invoke(chain, invoker, args, correlationId, callbackRoutingChain);
+ } 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 {
+ out.writeObject(serviceName);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ serviceName = (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");
+ }
+ wire = owner.getInboundWire(serviceName);
+ }
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java
new file mode 100644
index 0000000000..d0d82484e3
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.HashMap;
+import java.util.Map;
+
+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.wire.AbstractInboundInvocationHandler;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.WireInvocationHandler;
+
+import org.apache.tuscany.core.wire.WireUtils;
+
+
+/**
+ * Receives a request from a proxy and performs an invocation on an {@link org.apache.tuscany.spi.wire.InboundWire} via
+ * an {@link InboundInvocationChain}
+ *
+ * @version $Rev$ $Date$
+ */
+public final class JDKInboundInvocationHandler extends AbstractInboundInvocationHandler
+ implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable {
+ private static final long serialVersionUID = -307902641125881043L;
+
+ /*
+ * an association of an operation to chain holder. The holder contains the 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;
+ private transient WorkContext context;
+ private String serviceName;
+ private Class<?> interfaze;
+
+ /**
+ * Constructor used for deserialization only
+ */
+ public JDKInboundInvocationHandler() {
+ }
+
+ public JDKInboundInvocationHandler(Class<?> interfaze, InboundWire wire, WorkContext context) {
+ this.context = context;
+ this.serviceName = wire.getServiceName();
+ this.interfaze = interfaze;
+ init(interfaze, wire);
+ }
+
+ public void setWorkContext(WorkContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Dispatches a client request made on a proxy
+ */
+ 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());
+ }
+ InboundInvocationChain chain = holder.chain;
+ TargetInvoker invoker;
+ if (holder.cachedInvoker == 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.cachedInvoker = (TargetInvoker) chain.getTargetInvoker().clone();
+ invoker = holder.cachedInvoker;
+ } else {
+ invoker = chain.getTargetInvoker();
+ }
+ } else {
+ assert chain != null;
+ invoker = chain.getTargetInvoker();
+ }
+ context.setCurrentCorrelationId(null);
+ return invoke(chain, invoker, args);
+ }
+
+
+ public Object invoke(Method method, Object[] args) throws Throwable {
+ return invoke(null, method, args);
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(serviceName);
+ out.writeObject(interfaze);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ serviceName = (String) in.readObject();
+ interfaze = (Class<?>) in.readObject();
+ }
+
+ public void reactivate() throws ReactivationException {
+ // TODO this method will be extremely slow - look to optimize
+ AtomicComponent owner = context.getCurrentAtomicComponent();
+ if (owner == null) {
+ throw new ReactivationException("Current atomic component not set on work context");
+ }
+ InboundWire wire = owner.getInboundWire(serviceName);
+ init(interfaze, wire);
+ }
+
+ private void init(Class<?> interfaze, InboundWire wire) {
+ this.chains = new HashMap<Method, ChainHolder>();
+ Method[] methods = interfaze.getMethods();
+ Map<Method, InboundInvocationChain> invocationChains = WireUtils.createInboundMapping(wire, methods);
+ for (Map.Entry<Method, InboundInvocationChain> entry : invocationChains.entrySet()) {
+ this.chains.put(entry.getKey(), new ChainHolder(entry.getValue()));
+ }
+ }
+
+ /**
+ * A holder used to associate an wire chain with a local copy of a target invoker that was previously cloned from
+ * the chain master
+ */
+ private class ChainHolder {
+ InboundInvocationChain chain;
+ TargetInvoker cachedInvoker;
+
+ public ChainHolder(InboundInvocationChain config) {
+ this.chain = config;
+ }
+
+ }
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java
new file mode 100644
index 0000000000..99cfb3c627
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+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.SCAObject;
+import org.apache.tuscany.spi.component.TargetInvocationException;
+import org.apache.tuscany.spi.component.WorkContext;
+import static org.apache.tuscany.spi.model.InteractionScope.CONVERSATIONAL;
+import org.apache.tuscany.spi.model.Scope;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.AbstractOutboundInvocationHandler;
+import org.apache.tuscany.spi.wire.OutboundChainHolder;
+import org.apache.tuscany.spi.wire.OutboundInvocationChain;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+import org.apache.tuscany.spi.wire.WireInvocationHandler;
+
+import org.apache.tuscany.core.implementation.PojoAtomicComponent;
+import org.apache.tuscany.core.wire.NoMethodForOperationException;
+import org.apache.tuscany.core.wire.WireUtils;
+
+
+/**
+ * Receives a request from a proxy and performs an invocation on an {@link org.apache.tuscany.spi.wire.OutboundWire} via
+ * an {@link org.apache.tuscany.spi.wire.OutboundInvocationChain}
+ *
+ * @version $Rev$ $Date$
+ */
+public final class JDKOutboundInvocationHandler extends AbstractOutboundInvocationHandler
+ implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable {
+ private static final long serialVersionUID = -6155278451964527325L;
+
+ /*
+ * 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, OutboundChainHolder> chains;
+ private transient WorkContext workContext;
+ private transient Object fromAddress;
+ private transient boolean wireContainerIsAtomicComponent;
+ private transient boolean contractHasCallback;
+ private transient boolean callbackIsImplemented;
+ private transient String callbackClassName;
+ private transient boolean contractIsRemotable;
+ private transient boolean contractIsConversational;
+ private transient String convIdForRemotableTarget;
+ private transient String convIdFromThread;
+ private String referenceName;
+ private Class<?> interfaze;
+
+ /**
+ * Constructor used for deserialization only
+ */
+ public JDKOutboundInvocationHandler() {
+ }
+
+ public JDKOutboundInvocationHandler(Class<?> interfaze, OutboundWire wire, WorkContext workContext)
+ throws NoMethodForOperationException {
+ this.workContext = workContext;
+ this.interfaze = interfaze;
+ init(interfaze, wire, null);
+ }
+
+ public JDKOutboundInvocationHandler(Class<?> interfaze,
+ OutboundWire wire,
+ Map<Method, OutboundChainHolder> mapping,
+ WorkContext workContext)
+ throws NoMethodForOperationException {
+ this.workContext = workContext;
+ this.interfaze = interfaze;
+ init(interfaze, wire, mapping);
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ OutboundChainHolder 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());
+ }
+ OutboundInvocationChain chain = holder.getChain();
+ TargetInvoker invoker;
+
+ 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());
+ invoker = holder.getCachedInvoker();
+ } else {
+ invoker = chain.getTargetInvoker();
+ }
+ } else {
+ assert chain != null;
+ invoker = chain.getTargetInvoker();
+ }
+
+ if (wireContainerIsAtomicComponent && contractHasCallback && !callbackIsImplemented) {
+ throw new NoRegisteredCallbackException("Instance is does not implement callback: "
+ + callbackClassName);
+ }
+
+ if (contractIsConversational) {
+ assert workContext != null : "Work context cannot be null for conversational invocation";
+ // Check for a conv id on thread and remember it
+ convIdFromThread = (String) workContext.getIdentifier(Scope.CONVERSATION);
+ if (contractIsRemotable) {
+ if (convIdForRemotableTarget == null) {
+ convIdForRemotableTarget = createConversationID();
+ }
+ // Always use the conv id for this target
+ workContext.setIdentifier(Scope.CONVERSATION, convIdForRemotableTarget);
+ } else if (convIdFromThread == null) {
+ String newConvId = createConversationID();
+ workContext.setIdentifier(Scope.CONVERSATION, newConvId);
+ }
+ }
+
+ Object result = invoke(chain, invoker, args, null, null);
+ if (contractIsConversational && contractIsRemotable) {
+ // Make sure we restore the remembered conv id to continue propagating
+ workContext.setIdentifier(Scope.CONVERSATION, convIdFromThread);
+ }
+ return result;
+ }
+
+ public Object invoke(Method method, Object[] args) throws Throwable {
+ return invoke(null, method, args);
+ }
+
+ protected Object getFromAddress() {
+ return contractHasCallback ? fromAddress : null;
+ }
+
+ public void setWorkContext(WorkContext context) {
+ workContext = context;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeObject(referenceName);
+ out.writeObject(interfaze);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ referenceName = (String) in.readObject();
+ interfaze = (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<OutboundWire> wires = owner.getOutboundWires().get(referenceName);
+ if (wires == null) {
+ throw new ReactivationException("Reference wire not found", referenceName, owner.getName());
+ }
+ // TODO handle multiplicity
+ OutboundWire wire = wires.get(0);
+ try {
+ init(interfaze, wire, null);
+ } catch (NoMethodForOperationException e) {
+ throw new ReactivationException(e);
+ }
+ }
+
+ private void init(Class<?> interfaze, OutboundWire wire, Map<Method, OutboundChainHolder> mapping)
+ throws NoMethodForOperationException {
+ ServiceContract contract = wire.getServiceContract();
+ this.referenceName = wire.getReferenceName();
+ SCAObject wireContainer = wire.getContainer();
+ this.fromAddress = (wireContainer == null) ? null : wireContainer.getName();
+ this.contractIsConversational = contract.getInteractionScope().equals(CONVERSATIONAL);
+ this.contractIsRemotable = contract.isRemotable();
+ this.contractHasCallback = contract.getCallbackClass() != null;
+ if (contractHasCallback) {
+ this.callbackClassName = contract.getCallbackClass().getName();
+ } else {
+ this.callbackClassName = null;
+ }
+ // FIXME JFM this should be done during the callback and not be dependent on PojoAtomicComponent
+ this.wireContainerIsAtomicComponent = wireContainer instanceof PojoAtomicComponent;
+ if (wireContainerIsAtomicComponent && contractHasCallback) {
+ this.callbackIsImplemented =
+ ((PojoAtomicComponent) wireContainer).implementsCallback(contract.getCallbackClass());
+ } else {
+ this.callbackIsImplemented = false;
+ }
+ if (mapping == null) {
+ chains = WireUtils.createInterfaceToWireMapping(interfaze, wire);
+ } else {
+ chains = mapping;
+ }
+ }
+
+ // TODO Temporary fix to return a string with a UUID
+ private String createConversationID() {
+ return UUID.randomUUID().toString();
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java
new file mode 100644
index 0000000000..e15b851351
--- /dev/null
+++ b/sca-java-1.x/branches/pre-spec-changes/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.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.wire.jdk;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+
+import org.osoa.sca.annotations.Constructor;
+import org.osoa.sca.annotations.EagerInit;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.WorkContext;
+import org.apache.tuscany.spi.policy.PolicyBuilderRegistry;
+import org.apache.tuscany.spi.wire.InboundWire;
+import org.apache.tuscany.spi.wire.OutboundChainHolder;
+import org.apache.tuscany.spi.wire.OutboundWire;
+import org.apache.tuscany.spi.wire.ProxyCreationException;
+import org.apache.tuscany.spi.wire.Wire;
+import org.apache.tuscany.spi.wire.WireInvocationHandler;
+
+import org.apache.tuscany.core.wire.WireServiceExtension;
+
+/**
+ * the default implementation of a wire service that uses JDK dynamic proxies
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+@EagerInit
+public class JDKWireService extends WireServiceExtension {
+
+ public JDKWireService() {
+ super(null, null);
+ }
+
+ @Constructor
+ public JDKWireService(@Autowire WorkContext context, @Autowire PolicyBuilderRegistry policyRegistry) {
+ super(context, policyRegistry);
+ }
+
+ public <T> T createProxy(Class<T> interfaze, Wire wire) throws ProxyCreationException {
+ assert interfaze != null;
+ assert wire != null;
+ if (wire instanceof InboundWire) {
+ InboundWire inbound = (InboundWire) wire;
+ JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(interfaze, inbound, context);
+ ClassLoader cl = interfaze.getClassLoader();
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ } else if (wire instanceof OutboundWire) {
+ OutboundWire outbound = (OutboundWire) wire;
+ JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(interfaze, outbound, context);
+ ClassLoader cl = interfaze.getClassLoader();
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ } else {
+ throw new ProxyCreationException("Invalid wire type", wire.getClass().getName());
+ }
+ }
+
+ public <T> T createProxy(Class<T> interfaze, Wire wire, Map<Method, OutboundChainHolder> mapping)
+ throws ProxyCreationException {
+ assert interfaze != null;
+ assert wire != null;
+ assert mapping != null;
+ if (wire instanceof InboundWire) {
+ InboundWire inbound = (InboundWire) wire;
+ JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(interfaze, inbound, context);
+ ClassLoader cl = interfaze.getClassLoader();
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ } else if (wire instanceof OutboundWire) {
+ OutboundWire outbound = (OutboundWire) wire;
+ JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(interfaze, outbound, context);
+ ClassLoader cl = interfaze.getClassLoader();
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ } else {
+ throw new ProxyCreationException("Invalid wire type", wire.getClass().getName());
+ }
+ }
+
+ public Object createCallbackProxy(Class<?> interfaze, InboundWire wire) throws ProxyCreationException {
+ ClassLoader cl = interfaze.getClassLoader();
+ JDKCallbackInvocationHandler handler = new JDKCallbackInvocationHandler(wire, context);
+ return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler));
+ }
+
+ public WireInvocationHandler createHandler(Class<?> interfaze, Wire wire) {
+ assert wire != null;
+ if (wire instanceof InboundWire) {
+ InboundWire inbound = (InboundWire) wire;
+ return new JDKInboundInvocationHandler(interfaze, inbound, context);
+ } else if (wire instanceof OutboundWire) {
+ OutboundWire outbound = (OutboundWire) wire;
+ return new JDKOutboundInvocationHandler(interfaze, outbound, context);
+ } else {
+ throw new ProxyCreationException("Invalid wire type", wire.getClass().getName());
+ }
+ }
+
+}