From 7abf5a347d0f5dc9a54cd6c443daafae9f4976fc Mon Sep 17 00:00:00 2001 From: antelder Date: Fri, 30 Oct 2009 12:18:56 +0000 Subject: Re-tag 2.0-M4 RC1 release git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@831279 13f79535-47bb-0310-9956-ffa450edef68 --- tags/java/sca/2.0-M4-RC1/modules/core/LICENSE | 205 +++++ .../2.0-M4-RC1/modules/core/META-INF/MANIFEST.MF | 67 ++ tags/java/sca/2.0-M4-RC1/modules/core/NOTICE | 6 + tags/java/sca/2.0-M4-RC1/modules/core/pom.xml | 89 +++ .../sca/core/assembly/RuntimeAssemblyFactory.java | 74 ++ .../core/assembly/impl/CompositeActivatorImpl.java | 846 +++++++++++++++++++++ .../core/assembly/impl/EndpointRegistryImpl.java | 208 +++++ .../core/assembly/impl/EndpointSerializerImpl.java | 111 +++ .../assembly/impl/ReferenceParameterProcessor.java | 98 +++ .../assembly/impl/ReferenceParametersImpl.java | 121 +++ .../core/assembly/impl/RuntimeComponentImpl.java | 111 +++ .../impl/RuntimeComponentReferenceImpl.java | 150 ++++ .../assembly/impl/RuntimeComponentServiceImpl.java | 169 ++++ .../core/assembly/impl/RuntimeEndpointImpl.java | 101 +++ .../impl/RuntimeEndpointReferenceImpl.java | 100 +++ .../sca/core/assembly/impl/RuntimeWireImpl.java | 787 +++++++++++++++++++ .../context/DefaultComponentContextFactory.java | 43 ++ .../core/context/DefaultRequestContextFactory.java | 40 + .../sca/core/context/ServiceReferenceExt.java | 60 ++ .../context/impl/CallbackServiceReferenceImpl.java | 154 ++++ .../core/context/impl/ComponentContextImpl.java | 496 ++++++++++++ .../sca/core/context/impl/RequestContextImpl.java | 118 +++ .../core/context/impl/ServiceReferenceImpl.java | 481 ++++++++++++ .../tuscany/sca/core/factory/InstanceWrapper.java | 48 ++ .../sca/core/factory/ObjectCreationException.java | 47 ++ .../tuscany/sca/core/factory/ObjectFactory.java | 35 + .../invocation/CallableReferenceObjectFactory.java | 63 ++ .../invocation/CallbackInterfaceInterceptor.java | 60 ++ .../invocation/CallbackReferenceObjectFactory.java | 50 ++ .../core/invocation/CallbackWireObjectFactory.java | 47 ++ .../sca/core/invocation/CglibProxyFactory.java | 149 ++++ .../DefaultProxyFactoryExtensionPoint.java | 95 +++ .../core/invocation/ExtensibleProxyFactory.java | 114 +++ .../core/invocation/ExtensibleWireProcessor.java | 44 ++ .../core/invocation/NonBlockingInterceptor.java | 202 +++++ .../core/invocation/ProxyCreationException.java | 48 ++ .../tuscany/sca/core/invocation/ProxyFactory.java | 88 +++ .../invocation/ProxyFactoryExtensionPoint.java | 53 ++ .../sca/core/invocation/RuntimeWireInvoker.java | 268 +++++++ .../sca/core/invocation/WireObjectFactory.java | 55 ++ .../invocation/impl/AsyncJDKInvocationHandler.java | 93 +++ .../sca/core/invocation/impl/AsyncResponse.java | 68 ++ .../core/invocation/impl/InvocationChainImpl.java | 195 +++++ .../impl/JDKCallbackInvocationHandler.java | 80 ++ .../core/invocation/impl/JDKInvocationHandler.java | 537 +++++++++++++ .../sca/core/invocation/impl/JDKProxyFactory.java | 177 +++++ .../core/invocation/impl/MessageFactoryImpl.java | 36 + .../sca/core/invocation/impl/MessageImpl.java | 117 +++ .../impl/NoMethodForOperationException.java | 45 ++ .../sca/core/invocation/impl/PhaseManager.java | 313 ++++++++ .../sca/core/invocation/impl/PhaseSorter.java | 236 ++++++ .../core/runtime/DefaultDomainRegistryFactory.java | 156 ++++ .../runtime/impl/EndpointReferenceBinderImpl.java | 299 ++++++++ .../sca/core/scope/AbstractScopeContainer.java | 196 +++++ .../sca/core/scope/DefaultScopeRegistry.java | 40 + .../org/apache/tuscany/sca/core/scope/Scope.java | 62 ++ .../tuscany/sca/core/scope/ScopeContainer.java | 158 ++++ .../sca/core/scope/ScopeContainerFactory.java | 32 + .../tuscany/sca/core/scope/ScopeRegistry.java | 43 ++ .../core/scope/ScopedImplementationProvider.java | 65 ++ .../sca/core/scope/ScopedRuntimeComponent.java | 40 + .../sca/core/scope/TargetDestructionException.java | 44 ++ .../core/scope/TargetInitializationException.java | 44 ++ .../sca/core/scope/TargetNotFoundException.java | 44 ++ .../sca/core/scope/TargetResolutionException.java | 44 ++ .../core/scope/impl/CompositeScopeContainer.java | 87 +++ .../scope/impl/CompositeScopeContainerFactory.java | 40 + .../sca/core/scope/impl/ScopeRegistryImpl.java | 70 ++ .../core/scope/impl/StatelessScopeContainer.java | 61 ++ .../scope/impl/StatelessScopeContainerFactory.java | 40 + .../sca/core/work/impl/DefaultWorkScheduler.java | 195 +++++ .../sca/core/work/impl/ThreadPoolWorkManager.java | 228 ++++++ .../apache/tuscany/sca/core/work/impl/Work.java | 65 ++ .../tuscany/sca/core/work/impl/WorkEvent.java | 80 ++ .../tuscany/sca/core/work/impl/WorkItem.java | 167 ++++ .../tuscany/sca/core/work/impl/WorkListener.java | 32 + ...org.apache.tuscany.sca.assembly.AssemblyFactory | 18 + ...che.tuscany.sca.context.ComponentContextFactory | 17 + ...pache.tuscany.sca.context.RequestContextFactory | 17 + ...ca.contribution.processor.StAXArtifactProcessor | 20 + ....sca.core.invocation.ProxyFactoryExtensionPoint | 19 + ...org.apache.tuscany.sca.core.scope.ScopeRegistry | 19 + ...rg.apache.tuscany.sca.invocation.MessageFactory | 19 + ...g.apache.tuscany.sca.runtime.CompositeActivator | 19 + ...pache.tuscany.sca.runtime.DomainRegistryFactory | 18 + ...che.tuscany.sca.runtime.EndpointReferenceBinder | 18 + ...org.apache.tuscany.sca.runtime.EndpointRegistry | 18 + ...g.apache.tuscany.sca.runtime.EndpointSerializer | 17 + .../org.apache.tuscany.sca.work.WorkScheduler | 19 + .../endpoint-validation-messages.properties | 22 + .../impl/InvocationChainImplTestCase.java | 93 +++ .../core/invocation/impl/PhaseManagerTestCase.java | 50 ++ .../core/invocation/impl/PhaseSorterTestCase.java | 67 ++ .../tuscany/sca/core/work/impl/FailingWork.java | 54 ++ .../core/work/impl/JSR237MyFailingRunnable.java | 43 ++ .../sca/core/work/impl/JSR237MyRunnable.java | 71 ++ .../sca/core/work/impl/JSR237MyRunnerListener.java | 154 ++++ .../work/impl/Jsr237WorkSchedulerTestCase.java | 240 ++++++ .../sca/core/work/impl/TestWorkListener.java | 153 ++++ .../work/impl/ThreadPoolWorkManagerTestCase.java | 227 ++++++ .../tuscany/sca/core/work/impl/TimeDelayWork.java | 86 +++ .../apache/tuscany/sca/scope/ScopeTestCase.java | 66 ++ .../org.apache.tuscany.sca.invocation.PhaseTest | 24 + 103 files changed, 11918 insertions(+) create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/LICENSE create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/META-INF/MANIFEST.MF create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/NOTICE create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/pom.xml create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/DefaultDomainRegistryFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/endpoint-validation-messages.properties create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java create mode 100644 tags/java/sca/2.0-M4-RC1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest (limited to 'tags/java/sca/2.0-M4-RC1/modules/core') diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/LICENSE b/tags/java/sca/2.0-M4-RC1/modules/core/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/META-INF/MANIFEST.MF b/tags/java/sca/2.0-M4-RC1/modules/core/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..98800de77d --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/META-INF/MANIFEST.MF @@ -0,0 +1,67 @@ +Manifest-Version: 1.0 +Export-Package: org.apache.tuscany.sca.core.assembly;version="2.0.0";uses:="org.apache.tuscany.sca.assembly,org.apache.tuscany.sca.core", + org.apache.tuscany.sca.core.context;version="2.0.0"; + uses:="javax.xml.stream, + org.apache.tuscany.sca.runtime, + org.apache.tuscany.sca.assembly, + org.apache.tuscany.sca.context, + org.oasisopen.sca, + org.apache.tuscany.sca.core", + org.apache.tuscany.sca.core.factory;version="2.0.0", + org.apache.tuscany.sca.core.invocation;version="2.0.0"; + uses:="org.apache.tuscany.sca.invocation, + org.apache.tuscany.sca.runtime, + org.apache.tuscany.sca.assembly, + org.oasisopen.sca, + org.apache.tuscany.sca.work, + org.apache.tuscany.sca.core.factory, + org.apache.tuscany.sca.core.context.impl, + org.apache.tuscany.sca.core, + org.apache.tuscany.sca.interfacedef", + org.apache.tuscany.sca.core.scope;version="2.0.0"; + uses:="org.apache.tuscany.sca.runtime, + org.apache.tuscany.sca.provider, + org.apache.tuscany.sca.core.scope.impl, + org.apache.tuscany.sca.core.factory" +Tool: Bnd-0.0.255 +Bundle-Name: Apache Tuscany SCA Core Runtime +Created-By: 1.6.0_07 (Sun Microsystems Inc.) +Bundle-Vendor: The Apache Software Foundation +Bundle-Version: 2.0.0 +Bnd-LastModified: 1225397162265 +Bundle-ManifestVersion: 2 +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-Description: Apache Tuscany SCA Core Runtime +Import-Package: javax.security.auth, + javax.xml.namespace, + javax.xml.stream, + net.sf.cglib.proxy;resolution:=optional, + org.apache.tuscany.sca.assembly;version="2.0.0", + org.apache.tuscany.sca.assembly.builder;version="2.0.0", + org.apache.tuscany.sca.assembly.impl;version="2.0.0", + org.apache.tuscany.sca.common.java.collection;version="2.0.0", + org.apache.tuscany.sca.context;version="2.0.0", + org.apache.tuscany.sca.contribution.processor;version="2.0.0", + org.apache.tuscany.sca.contribution.resolver;version="2.0.0", + org.apache.tuscany.sca.core;version="2.0.0", + org.apache.tuscany.sca.core.assembly;version="2.0.0", + org.apache.tuscany.sca.core.context;version="2.0.0", + org.apache.tuscany.sca.core.factory;version="2.0.0", + org.apache.tuscany.sca.core.invocation;version="2.0.0", + org.apache.tuscany.sca.core.scope;version="2.0.0", + org.apache.tuscany.sca.extensibility;version="2.0.0", + org.apache.tuscany.sca.interfacedef;version="2.0.0", + org.apache.tuscany.sca.interfacedef.impl;version="2.0.0";resolution:=optional, + org.apache.tuscany.sca.interfacedef.java;version="2.0.0", + org.apache.tuscany.sca.interfacedef.util;version="2.0.0", + org.apache.tuscany.sca.invocation;version="2.0.0", + org.apache.tuscany.sca.monitor;version="2.0.0", + org.apache.tuscany.sca.policy;version="2.0.0", + org.apache.tuscany.sca.provider;version="2.0.0", + org.apache.tuscany.sca.runtime;version="2.0.0", + org.apache.tuscany.sca.work;version="2.0.0", + org.oasisopen.sca;version="2.0.0", + org.oasisopen.sca.annotation;version="2.0.0" +Bundle-SymbolicName: org.apache.tuscany.sca.core +Bundle-DocURL: http://www.apache.org/ +Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/NOTICE b/tags/java/sca/2.0-M4-RC1/modules/core/NOTICE new file mode 100644 index 0000000000..25bb89c9b2 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2009 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/pom.xml b/tags/java/sca/2.0-M4-RC1/modules/core/pom.xml new file mode 100644 index 0000000000..88a7915820 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/pom.xml @@ -0,0 +1,89 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-M4 + ../pom.xml + + tuscany-core + Apache Tuscany SCA Core Runtime + + + + org.apache.tuscany.sca + tuscany-extensibility + 2.0-M4 + + + + org.apache.tuscany.sca + tuscany-core-spi + 2.0-M4 + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-M4 + + + + org.apache.tuscany.sca + tuscany-interface-java + 2.0-M4 + + + + org.apache.geronimo.specs + geronimo-stax-api_1.0_spec + 1.0.1 + + + + org.codehaus.woodstox + wstx-asl + 3.2.4 + runtime + + + stax + stax-api + + + + + + cglib + cglib + 2.2 + + + + asm + asm + 3.1 + + + + + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java new file mode 100644 index 0000000000..8c84a9e399 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.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.sca.core.assembly; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentReferenceImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentServiceImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl; + + +/** + * The runtime version of assembly factory + * @version $Rev$ $Date$ + */ +public class RuntimeAssemblyFactory extends DefaultAssemblyFactory implements AssemblyFactory { + + public RuntimeAssemblyFactory(ExtensionPointRegistry registry) { + super(registry); + } + + @Override + public Component createComponent() { + return new RuntimeComponentImpl(); + } + + @Override + public ComponentReference createComponentReference() { + return new RuntimeComponentReferenceImpl(); + } + + @Override + public ComponentService createComponentService() { + return new RuntimeComponentServiceImpl(); + } + + @Override + public Endpoint createEndpoint() { + // Create an instance of EndpointImpl that can be serialized/deserialized using the Tuscany + // runtime extension points and extensions + return new RuntimeEndpointImpl(registry); + } + + @Override + public EndpointReference createEndpointReference() { + return new RuntimeEndpointReferenceImpl(registry); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java new file mode 100644 index 0000000000..1c4ded13fc --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java @@ -0,0 +1,846 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.ActivationException; +import org.apache.tuscany.sca.runtime.CompositeActivator; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeActivatorImpl implements CompositeActivator { + final Logger logger = Logger.getLogger(CompositeActivatorImpl.class.getName()); + + private final ExtensionPointRegistry extensionPoints; + private final AssemblyFactory assemblyFactory; + private final MessageFactory messageFactory; + private final InterfaceContractMapper interfaceContractMapper; + private final ScopeRegistry scopeRegistry; + private final WorkScheduler workScheduler; + private final RuntimeWireProcessor wireProcessor; + private final ProviderFactoryExtensionPoint providerFactories; + + public CompositeActivatorImpl(ExtensionPointRegistry extensionPoints) { + this.extensionPoints = extensionPoints; + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + FactoryExtensionPoint factories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + this.messageFactory = factories.getFactory(MessageFactory.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + this.scopeRegistry = utilities.getUtility(ScopeRegistry.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + this.wireProcessor = new ExtensibleWireProcessor(extensionPoints.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); + this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class); + } + + //========================================================================= + // Activation + //========================================================================= + + // Composite activation/deactivation + + public void activate(CompositeContext compositeContext, Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + activateComponent(compositeContext, component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + public void deactivate(Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + deactivateComponent(component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + // Component activation/deactivation + + public void activateComponent(CompositeContext compositeContext, Component component) + throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component: " + component.getURI()); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + activate(compositeContext, (Composite) implementation); + } else if (implementation != null) { + addImplementationProvider((RuntimeComponent) component, + implementation); + addScopeContainer(component); + } + + for (ComponentService service : component.getServices()) { + activate(compositeContext, + (RuntimeComponent) component, (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + activate(compositeContext, + (RuntimeComponent) component, (RuntimeComponentReference) reference); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + public void deactivateComponent(Component component) + throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component: " + component.getURI()); + } + for (ComponentService service : component.getServices()) { + deactivate((RuntimeComponent) component, + (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + deactivate((RuntimeComponent) component, + (RuntimeComponentReference) reference); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + deactivate((Composite) implementation); + } else if (implementation != null) { + removeImplementationProvider((RuntimeComponent) component); + removeScopeContainer(component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + // add/remove artifacts required to get the implementation going + + private void addImplementationProvider(RuntimeComponent component, Implementation implementation) { + ImplementationProviderFactory providerFactory = + (ImplementationProviderFactory)providerFactories.getProviderFactory(implementation.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ImplementationProvider implementationProvider = + providerFactory.createImplementationProvider(component, implementation); + if (implementationProvider != null) { + component.setImplementationProvider(implementationProvider); + } + } else { + throw new IllegalStateException("Provider factory not found for class: " + implementation.getClass() + .getName()); + } + for (PolicyProviderFactory f : providerFactories.getPolicyProviderFactories()) { + PolicyProvider policyProvider = f.createImplementationPolicyProvider(component); + if (policyProvider != null) { + component.addPolicyProvider(policyProvider); + } + } + + } + + private void removeImplementationProvider(RuntimeComponent component) { + component.setImplementationProvider(null); + component.getPolicyProviders().clear(); + } + + private void addScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent); + runtimeComponent.setScopeContainer(scopeContainer); + } + + private void removeScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = runtimeComponent.getScopeContainer(); + runtimeComponent.setScopeContainer(null); + } + + + // Service activation/deactivation + + public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentService service) { + if (service.getService() == null) { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Skipping component service not defined in the component type: " + component.getURI() + + "#" + + service.getName()); + } + return; + } + + /* TODO - EPR - activate services at all levels as promoted endpoin references are maintained + * on the higher level services + if (service.getService() instanceof CompositeService) { + return; + } + */ + + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component service: " + component.getURI() + "#" + service.getName()); + } + + for (Endpoint endpoint : service.getEndpoints()) { + addServiceBindingProvider(endpoint, component, service, endpoint.getBinding()); + } + addServiceWires(compositeContext, component, service); + } + + public void deactivate(RuntimeComponent component, RuntimeComponentService service) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component service: " + component.getURI() + "#" + service.getName()); + } + removeServiceWires(service); + for (Binding binding : service.getBindings()) { + removeServiceBindingProvider(component, service, binding); + } + } + + private ServiceBindingProvider addServiceBindingProvider( + Endpoint endpoint, + RuntimeComponent component, RuntimeComponentService service, + Binding binding) { + BindingProviderFactory providerFactory = (BindingProviderFactory) providerFactories + .getProviderFactory(binding.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ServiceBindingProvider bindingProvider = providerFactory + .createServiceBindingProvider(endpoint); + if (bindingProvider != null) { + ((RuntimeComponentService) service).setBindingProvider(binding, + bindingProvider); + } + for (PolicyProviderFactory f : providerFactories.getPolicyProviderFactories()) { + PolicyProvider policyProvider = f.createServicePolicyProvider(endpoint); + if (policyProvider != null) { + service.addPolicyProvider(binding, policyProvider); + } + } + return bindingProvider; + } else { + throw new IllegalStateException( + "Provider factory not found for binding: " + + binding.getType()); + } + } + + private void removeServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, Binding binding) { + service.setBindingProvider(binding, null); + for (Binding b : service.getBindings()) { + List pps = service.getPolicyProviders(b); + if (pps != null) { + pps.clear(); + } + } + } + + private void addServiceWires(CompositeContext compositeContext, Component serviceComponent, ComponentService service) { + if (!(service instanceof RuntimeComponentService)) { + return; + } + + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + + // Add a wire for each service Endpoint + for ( Endpoint endpoint : runtimeService.getEndpoints()){ + + // fluff up a fake endpoint reference as we are on the service side + // so we need to represent the reference that will call us + EndpointReference endpointReference = assemblyFactory.createEndpointReference(); + endpointReference.setBinding(endpoint.getBinding()); + endpointReference.setTargetEndpoint(endpoint); + endpointReference.setStatus(EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED); + + // create the interface contract for the binding and service ends of the wire + // that are created as forward only contracts + // FIXME: [rfeng] We might need a better way to get the impl interface contract + Service targetService = service.getService(); + if (targetService == null) { + targetService = service; + } + endpoint.setInterfaceContract(targetService.getInterfaceContract().makeUnidirectional(false)); + endpointReference.setInterfaceContract(getServiceBindingInterfaceContract(service, endpoint.getBinding())); + + // create the wire + RuntimeWire wire = new RuntimeWireImpl(compositeContext, + false, + endpointReference, + endpoint, + interfaceContractMapper, + workScheduler, + wireProcessor, + messageFactory); + + // TODO - EPR - TUSCANY-3187 - keep and eye on this as to code + // has been reported to be working without this fix in some + // environments + //runtimeService.getRuntimeWires().add(wire); + ((RuntimeComponentService)endpoint.getService()).getRuntimeWires().add(wire); + } + } + + private void removeServiceWires(ComponentService service) { + if (!(service instanceof RuntimeComponentService)) { + return; + } + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + runtimeService.getRuntimeWires().clear(); + } + + private InterfaceContract getServiceBindingInterfaceContract(ComponentService service, Binding binding) { + InterfaceContract interfaceContract = service.getInterfaceContract(); + + ServiceBindingProvider provider = ((RuntimeComponentService)service).getBindingProvider(binding); + if (provider != null) { + InterfaceContract bindingContract = provider.getBindingInterfaceContract(); + if (bindingContract != null) { + interfaceContract = bindingContract; + } + } + return interfaceContract.makeUnidirectional(false); + } + + // Reference activation/deactivation + + public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component reference: " + component.getURI() + "#" + reference.getName()); + } + + // set the parent component onto the reference. It's used at start time when the + // reference is asked to return it's runtime wires. If there are none the reference + // asks the component context to start the reference which creates the wires + reference.setComponent(component); + + // TODO reference wires are added at component start for some reason + } + + public void deactivate(RuntimeComponent component, RuntimeComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component reference: " + component.getURI() + "#" + reference.getName()); + } + removeReferenceWires(reference); + for (EndpointReference endpointReference : reference.getEndpointReferences()) { + if (endpointReference.getBinding() != null){ + removeReferenceBindingProvider(component, reference, endpointReference.getBinding()); + } + } + } +/* + private ReferenceBindingProvider addReferenceBindingProvider( + RuntimeComponent component, RuntimeComponentReference reference, + Binding binding) { + BindingProviderFactory providerFactory = (BindingProviderFactory) providerFactories + .getProviderFactory(binding.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ReferenceBindingProvider bindingProvider = providerFactory + .createReferenceBindingProvider( + (RuntimeComponent) component, + (RuntimeComponentReference) reference, binding); + if (bindingProvider != null) { + ((RuntimeComponentReference) reference).setBindingProvider( + binding, bindingProvider); + } + for (PolicyProviderFactory f : providerFactories + .getPolicyProviderFactories()) { + PolicyProvider policyProvider = f + .createReferencePolicyProvider(component, reference, + binding); + if (policyProvider != null) { + reference.addPolicyProvider(binding, policyProvider); + } + } + + return bindingProvider; + } else { + throw new IllegalStateException( + "Provider factory not found for binding: " + + binding.getClass().getType()); + } + } +*/ + private void removeReferenceBindingProvider(RuntimeComponent component, + RuntimeComponentReference reference, Binding binding) { + reference.setBindingProvider(binding, null); + for (Binding b : reference.getBindings()) { + List pps = reference.getPolicyProviders(b); + if (pps != null) { + pps.clear(); + } + } + } + + private void removeReferenceWires(ComponentReference reference) { + if (!(reference instanceof RuntimeComponentReference)) { + return; + } + + // TODO - EPR what is this all about? + // [rfeng] Comment out the following statements to avoid the on-demand activation + // RuntimeComponentReference runtimeRef = (RuntimeComponentReference)reference; + // runtimeRef.getRuntimeWires().clear(); + } + + //========================================================================= + // Start + //========================================================================= + + // Composite start/stop + + public void start(CompositeContext compositeContext, Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + start(compositeContext, component); + } + } + + public void stop(CompositeContext compositeContext, Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping composite: " + composite.getName()); + } + for (final Component component : composite.getComponents()) { + stop(compositeContext, component); + } + } + + // Component start/stop + + public void start(CompositeContext compositeContext, Component component) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component: " + component.getURI()); + } + RuntimeComponent runtimeComponent = ((RuntimeComponent)component); + if(runtimeComponent.isStarted()) { + return; + } + + compositeContext.bindComponent(runtimeComponent); + + // Reference bindings aren't started until the wire is first used + + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component service: " + component.getURI() + "#" + service.getName()); + } + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + for (Endpoint endpoint : service.getEndpoints()) { + // FIXME: Should the policy providers be started before the endpoint is started? + for (PolicyProvider policyProvider : runtimeService.getPolicyProviders(endpoint.getBinding())) { + policyProvider.start(); + } + + final ServiceBindingProvider bindingProvider = runtimeService.getBindingProvider(endpoint.getBinding()); + if (bindingProvider != null) { + // bindingProvider.start(); + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + bindingProvider.start(); + return null; + } + }); + compositeContext.getEndpointRegistry().addEndpoint(endpoint); + } + } + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + start(compositeContext, (Composite)implementation); + } else { + for (PolicyProvider policyProvider : runtimeComponent.getPolicyProviders()) { + policyProvider.start(); + } + ImplementationProvider implementationProvider = runtimeComponent.getImplementationProvider(); + if (implementationProvider != null) { + implementationProvider.start(); + } + } + + if (component instanceof ScopedRuntimeComponent) { + ScopedRuntimeComponent scopedRuntimeComponent = (ScopedRuntimeComponent)component; + if (scopedRuntimeComponent.getScopeContainer() != null) { + scopedRuntimeComponent.getScopeContainer().start(); + } + } + + runtimeComponent.setStarted(true); + } + + public void stop(CompositeContext compositeContext, Component component) { + if (!((RuntimeComponent)component).isStarted()) { + return; + } + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component: " + component.getURI()); + } + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component service: " + component.getURI() + "#" + service.getName()); + } + for (Endpoint endpoint : service.getEndpoints()) { + compositeContext.getEndpointRegistry().removeEndpoint(endpoint); + final ServiceBindingProvider bindingProvider = ((RuntimeComponentService)service).getBindingProvider(endpoint.getBinding()); + if (bindingProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + bindingProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ((RuntimeComponentService)service).getPolicyProviders(endpoint + .getBinding())) { + policyProvider.stop(); + } + } + } + for (ComponentReference reference : component.getReferences()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + + for (EndpointReference endpointReference : reference.getEndpointReferences()) { + compositeContext.getEndpointRegistry().removeEndpointReference(endpointReference); + final ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding()); + if (bindingProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + bindingProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ((RuntimeComponentReference)reference) + .getPolicyProviders(endpointReference.getBinding())) { + policyProvider.stop(); + } + + } + } + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + stop(compositeContext, (Composite)implementation); + } else { + final ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider(); + if (implementationProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + implementationProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ((RuntimeComponent)component).getPolicyProviders()) { + policyProvider.stop(); + } + } + + if (component instanceof ScopedRuntimeComponent) { + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + if (runtimeComponent.getScopeContainer() != null && + runtimeComponent.getScopeContainer().getLifecycleState() != ScopeContainer.STOPPED) { + runtimeComponent.getScopeContainer().stop(); + } + } + + ((RuntimeComponent)component).setStarted(false); + } + + // Service start/stop + + // TODO - EPR done as part of the component start above + + // Reference start/stop + // Used by component context start + // TODO - EPR I don't know why reference wires don't get added until component start + + public void start(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference componentReference) { + synchronized (componentReference) { + + if (!(componentReference instanceof RuntimeComponentReference)) { + return; + } + + /* The way it was + // create a wire for each endpoint reference. An endpoint reference says that a + // target has been specified and hence the reference has been wired in some way. + // The service may not have been found yet, depending on the way the composite + // is deployed, but it is expected to be found. In the case where the reference + // is unwired (a target has not been specified) there will be no endpoint + // reference and this will lead to null being injected + for (EndpointReference2 endpointReference : componentReference.getEndpointReferences()){ + + // if there is a binding an endpoint has been found for the endpoint reference + if (endpointReference.getBinding() != null){ + + // add the binding provider. This is apparently a repeat + // of previous configuration as self references are created + // on the fly and miss the previous point where providers are added + RuntimeComponentReference runtimeRef = (RuntimeComponentReference)componentReference; + + if (runtimeRef.getBindingProvider(endpointReference.getBinding()) == null) { + addReferenceBindingProvider(component, componentReference, endpointReference.getBinding()); + } + + // start the binding provider + final ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding()); + + if (bindingProvider != null) { + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + bindingProvider.start(); + return null; + } + }); + } + + // add the wire + addReferenceWire(component, componentReference, endpointReference); + } + } + */ + + // create a wire for each endpoint reference. An endpoint reference says either that + // - a target has been specified and hence the reference has been wired in some way. + // - an unwired binding ha been specified + // and endpoint reference representing a wired reference may not at this point + // be resolved (the service to which it points may not be present in the + // current composite). Endpoint reference resolution takes place when the wire + // is first used (when the chains are created) + for (EndpointReference endpointReference : componentReference.getEndpointReferences()){ + addReferenceWire(compositeContext, component, componentReference, endpointReference); + component.getComponentContext().getCompositeContext().getEndpointRegistry().addEndpointReference(endpointReference); + } + + } + } + + public void stop(Component component, ComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + RuntimeComponent runtimeComponent = (RuntimeComponent) component; + EndpointRegistry endpointRegistry = runtimeComponent.getComponentContext().getCompositeContext().getEndpointRegistry(); + for ( EndpointReference endpointReference : runtimeRef.getEndpointReferences()){ + endpointRegistry.removeEndpointReference(endpointReference); + ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding()); + if (bindingProvider != null) { + bindingProvider.stop(); + } + for (PolicyProvider policyProvider : ((RuntimeComponentReference)reference) + .getPolicyProviders(endpointReference.getBinding())) { + policyProvider.stop(); + } + } + } + + private void addReferenceWire(CompositeContext compositeContext, Component component, ComponentReference reference, EndpointReference endpointReference) { + RuntimeComponentReference runtimeRef = (RuntimeComponentReference)reference; + + // Use the interface contract of the reference on the component type and if there + // isn't one then use the one from the reference itself + Reference componentTypeRef = reference.getReference(); + + InterfaceContract sourceContract; + if (componentTypeRef == null || componentTypeRef.getInterfaceContract() == null) { + sourceContract = reference.getInterfaceContract(); + } else { + sourceContract = componentTypeRef.getInterfaceContract(); + } + + // TODO - EPR - interface contract seems to be null in the implementation.web + // case. Not introspecting the CT properly? + if (sourceContract == null){ + // TODO - Can't do this with move of matching to wire + // take the contract from the service to which the reference is connected + sourceContract = endpointReference.getTargetEndpoint().getInterfaceContract(); + reference.setInterfaceContract(sourceContract); + } + + endpointReference.setInterfaceContract(sourceContract.makeUnidirectional(false)); + +/* TODO - EPR should have been done previously during matching + ComponentService callbackService = reference.getCallbackService(); + if (callbackService != null) { + // select a reference callback binding to pass with invocations on this wire + Binding callbackBinding = null; + for (Binding binding : callbackService.getBindings()) { + // first look for a callback binding whose name matches the reference binding name + if (refBinding.getName().startsWith(binding.getName())) { + callbackBinding = binding; + break; + } + } + // if no callback binding found, try again based on reference binding type + if (callbackBinding == null) { + callbackBinding = callbackService.getBinding(refBinding.getClass()); + } + InterfaceContract callbackContract = callbackService.getInterfaceContract(); + EndpointReference callbackEndpoint = + new EndpointReferenceImpl((RuntimeComponent)refComponent, callbackService, callbackBinding, + callbackContract); + wireSource.setCallbackEndpoint(callbackEndpoint); + } +*/ + +/* TODO - EPR can't do this until the binding matches the EPR + InterfaceContract bindingContract = getInterfaceContract(reference, endpointReference.getBinding()); + Endpoint2 endpoint = endpointReference.getTargetEndpoint(); + endpoint.setInterfaceContract(bindingContract); +*/ + +/* TODO - EPR review in the light of new matching code + // TUSCANY-2029 - We should use the URI of the serviceBinding because the target may be a Component in a + // nested composite. + if (serviceBinding != null) { + wireTarget.setURI(serviceBinding.getURI()); + } +*/ + + // create the wire + // null endpoint passed in here as the endpoint reference may + // not be resolved yet + RuntimeWire wire = new RuntimeWireImpl(compositeContext, + true, + endpointReference, + null, + interfaceContractMapper, + workScheduler, + wireProcessor, + messageFactory); + runtimeRef.getRuntimeWires().add(wire); + + } + + private InterfaceContract getInterfaceContract(ComponentReference reference, Binding binding) { + InterfaceContract interfaceContract = reference.getInterfaceContract(); + ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding); + if (provider != null) { + InterfaceContract bindingContract = provider.getBindingInterfaceContract(); + if (bindingContract != null) { + interfaceContract = bindingContract; + } + } + return interfaceContract.makeUnidirectional(false); + } + + + /* TODO - EPR - Resolved via registry now + public Component resolve(String componentURI) { + for (Composite composite : domainComposite.getIncludes()) { + Component component = resolve(composite, componentURI); + if (component != null) { + return component; + } + } + return null; + } + + + public Component resolve(Composite composite, String componentURI) { + for (Component component : composite.getComponents()) { + String uri = component.getURI(); + if (uri.equals(componentURI)) { + return component; + } + if (componentURI.startsWith(uri)) { + Implementation implementation = component.getImplementation(); + if (!(implementation instanceof Composite)) { + return null; + } + return resolve((Composite)implementation, componentURI); + } + } + return null; + } + */ +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java new file mode 100644 index 0000000000..2ad61963e0 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.runtime.EndpointListener; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * A EndpointRegistry implementation that sees registrations from the same JVM + */ +public class EndpointRegistryImpl implements EndpointRegistry, LifeCycleListener { + private final Logger logger = Logger.getLogger(EndpointRegistryImpl.class.getName()); + + private List endpoints = new ArrayList(); + private List endpointreferences = new ArrayList(); + private List listeners = new ArrayList(); + + public EndpointRegistryImpl(ExtensionPointRegistry extensionPoints, String endpointRegistryURI, String domainURI) { + } + + public synchronized void addEndpoint(Endpoint endpoint) { + endpoints.add(endpoint); + for (EndpointListener listener : listeners) { + listener.endpointAdded(endpoint); + } + logger.info("Add endpoint - " + endpoint.toString()); + } + + public synchronized void addEndpointReference(EndpointReference endpointReference) { + endpointreferences.add(endpointReference); + logger.fine("Add endpoint reference - " + endpointReference.toString()); + } + + /** + * Parse the component/service/binding URI into an array of parts (componentURI, serviceName, bindingName) + * @param uri + * @return + */ + private String[] parse(String uri) { + String[] names = new String[3]; + int index = uri.lastIndexOf('#'); + if (index == -1) { + names[0] = uri; + } else { + names[0] = uri.substring(0, index); + String str = uri.substring(index + 1); + if (str.startsWith("service-binding(") && str.endsWith(")")) { + str = str.substring("service-binding(".length(), str.length() - 1); + String[] parts = str.split("/"); + if (parts.length != 2) { + throw new IllegalArgumentException("Invalid service-binding URI: " + uri); + } + names[1] = parts[0]; + names[2] = parts[1]; + } else if (str.startsWith("service(") && str.endsWith(")")) { + str = str.substring("service(".length(), str.length() - 1); + names[1] = str; + } else { + throw new IllegalArgumentException("Invalid component/service/binding URI: " + uri); + } + } + return names; + } + + private boolean matches(String target, String uri) { + String[] parts1 = parse(target); + String[] parts2 = parse(uri); + for (int i = 0; i < parts1.length; i++) { + if (parts1[i] == null || parts1[i].equals(parts2[i])) { + continue; + } else { + return false; + } + } + return true; + } + + public synchronized List findEndpoint(EndpointReference endpointReference) { + List foundEndpoints = new ArrayList(); + + logger.fine("Find endpoint for reference - " + endpointReference.toString()); + + if (endpointReference.getReference() != null) { + Endpoint targetEndpoint = endpointReference.getTargetEndpoint(); + for (Endpoint endpoint : endpoints) { + // TODO: implement more complete matching + if (matches(targetEndpoint.getURI(), endpoint.getURI())) { + foundEndpoints.add(endpoint); + logger.fine("Found endpoint with matching service - " + endpoint); + } + // else the service name doesn't match + } + } + + return foundEndpoints; + } + + public synchronized List findEndpointReference(Endpoint endpoint) { + return null; + } + + public synchronized void removeEndpoint(Endpoint endpoint) { + endpoints.remove(endpoint); + endpointRemoved(endpoint); + } + + private void endpointRemoved(Endpoint endpoint) { + for (EndpointListener listener : listeners) { + listener.endpointRemoved(endpoint); + } + logger.info("Remove endpoint - " + endpoint.toString()); + } + + public synchronized void removeEndpointReference(EndpointReference endpointReference) { + endpointreferences.remove(endpointReference); + logger.fine("Remove endpoint reference - " + endpointReference.toString()); + } + + public synchronized List getEndpointRefereneces() { + return endpointreferences; + } + + public synchronized List getEndpoints() { + return endpoints; + } + + public synchronized void addListener(EndpointListener listener) { + listeners.add(listener); + } + + public synchronized List getListeners() { + return listeners; + } + + public synchronized void removeListener(EndpointListener listener) { + listeners.remove(listener); + } + + public synchronized Endpoint getEndpoint(String uri) { + for (Endpoint ep : endpoints) { + String epURI = + ep.getComponent().getURI() + "#" + ep.getService().getName() + "/" + ep.getBinding().getName(); + if (epURI.equals(uri)) { + return ep; + } + if (ep.getBinding().getName() == null || ep.getBinding().getName().equals(ep.getService().getName())) { + epURI = ep.getComponent().getURI() + "#" + ep.getService().getName(); + if (epURI.equals(uri)) { + return ep; + } + } + } + return null; + + } + + public synchronized void updateEndpoint(String uri, Endpoint endpoint) { + Endpoint oldEndpoint = getEndpoint(uri); + if (oldEndpoint == null) { + throw new IllegalArgumentException("Endpoint is not found: " + uri); + } + endpoints.remove(oldEndpoint); + endpoints.add(endpoint); + for (EndpointListener listener : listeners) { + listener.endpointUpdated(oldEndpoint, endpoint); + } + } + + public synchronized void start() { + } + + public synchronized void stop() { + for (Iterator i = endpoints.iterator(); i.hasNext();) { + Endpoint ep = i.next(); + i.remove(); + endpointRemoved(ep); + } + endpointreferences.clear(); + listeners.clear(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java new file mode 100644 index 0000000000..82f8ebabea --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.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.sca.core.assembly.impl; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.EndpointSerializer; + +public class EndpointSerializerImpl implements EndpointSerializer { + private ExtensionPointRegistry registry; + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessor processor; + private StAXArtifactProcessor refProcessor; + + public EndpointSerializerImpl(ExtensionPointRegistry registry) { + this.registry =registry; + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + inputFactory = factories.getFactory(XMLInputFactory.class); + outputFactory = factories.getFactory(XMLOutputFactory.class); + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + processor = processors.getProcessor(Endpoint.class); + refProcessor = processors.getProcessor(EndpointReference.class); + } + + public void read(Endpoint endpoint, String xml) throws IOException { + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml)); + Endpoint result = processor.read(reader, new ProcessorContext(registry)); + endpoint.setComponent(result.getComponent()); + endpoint.setService(result.getService()); + endpoint.setBinding(result.getBinding()); + endpoint.setInterfaceContract(result.getService().getInterfaceContract()); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + + } + + public String write(Endpoint endpoint) throws IOException { + StringWriter sw = new StringWriter(); + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw); + processor.write(endpoint, writer, new ProcessorContext(registry)); + writer.flush(); + writer.close(); + return sw.toString(); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + public void read(EndpointReference endpointReference, String xml) throws IOException { + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml)); + EndpointReference result = refProcessor.read(reader, new ProcessorContext(registry)); + reader.close(); + endpointReference.setComponent(result.getComponent()); + endpointReference.setReference(result.getReference()); + endpointReference.setBinding(result.getBinding()); + endpointReference.setInterfaceContract(result.getReference().getInterfaceContract()); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + public String write(EndpointReference endpointReference) throws IOException { + StringWriter sw = new StringWriter(); + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw); + refProcessor.write(endpointReference, writer, new ProcessorContext(registry)); + writer.flush(); + writer.close(); + return sw.toString(); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java new file mode 100644 index 0000000000..4d6a98ca5f --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.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.sca.core.assembly.impl; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * Artifact processor for reference parameters. + * + * @version $Rev$ $Date$ + */ +public class ReferenceParameterProcessor implements StAXArtifactProcessor { + private static final QName REFERENCE_PARAMETERS = + new QName("http://tuscany.apache.org/xmlns/sca/1.1", "referenceParameters", "tuscany"); + + /** + * Constructs a new processor. + * + * @param modelFactories + */ + public ReferenceParameterProcessor(FactoryExtensionPoint modelFactories) { + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#getArtifactType() + */ + public QName getArtifactType() { + return REFERENCE_PARAMETERS; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#read(javax.xml.stream.XMLStreamReader, ProcessorContext) + */ + public ReferenceParameters read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + ReferenceParameters parameters = new ReferenceParametersImpl(); + parameters.setCallbackID(reader.getAttributeValue(null, "callbackID")); + return parameters; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#write(java.lang.Object, javax.xml.stream.XMLStreamWriter, ProcessorContext) + */ + public void write(ReferenceParameters model, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, + XMLStreamException { + writer.writeStartElement(REFERENCE_PARAMETERS.getPrefix(), + REFERENCE_PARAMETERS.getLocalPart(), + REFERENCE_PARAMETERS.getNamespaceURI()); + writer.writeNamespace(REFERENCE_PARAMETERS.getPrefix(), REFERENCE_PARAMETERS.getNamespaceURI()); + + if (model.getCallbackID() != null) { + writer.writeAttribute("callbackID", model.getCallbackID().toString()); + } + writer.writeEndElement(); + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#getModelType() + */ + public Class getModelType() { + return ReferenceParameters.class; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#resolve(java.lang.Object, org.apache.tuscany.sca.contribution.resolver.ModelResolver, ProcessorContext) + */ + public void resolve(ReferenceParameters model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java new file mode 100644 index 0000000000..7bd56271a5 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.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.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * @version $Rev$ $Date$ + */ +public class ReferenceParametersImpl implements ReferenceParameters { + private Object callbackID; + private EndpointReference callbackReference; + private Object callbackObjectID; + + /** + * @return the callbackID + */ + public Object getCallbackID() { + return callbackID; + } + /** + * @param callbackID the callbackID to set + */ + public void setCallbackID(Object callbackID) { + this.callbackID = callbackID; + } + + /** + * @see org.apache.tuscany.sca.runtime.ReferenceParameters#getCallbackReference() + */ + public EndpointReference getCallbackReference() { + return callbackReference; + } + /** + * @see org.apache.tuscany.sca.runtime.ReferenceParameters#setCallback(java.lang.Object) + */ + public void setCallbackReference(EndpointReference callback) { + this.callbackReference = callback; + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + /** + * @return the callbackObjectID + */ + public Object getCallbackObjectID() { + return callbackObjectID; + } + /** + * @param callbackObjectID the callbackObjectID to set + */ + public void setCallbackObjectID(Object callbackObjectID) { + this.callbackObjectID = callbackObjectID; + } + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((callbackID == null) ? 0 : callbackID.hashCode()); + result = prime * result + ((callbackObjectID == null) ? 0 : callbackObjectID.hashCode()); + result = prime * result + ((callbackReference == null) ? 0 : callbackReference.hashCode()); + return result; + } + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ReferenceParametersImpl)) + return false; + final ReferenceParametersImpl other = (ReferenceParametersImpl)obj; + if (callbackID == null) { + if (other.callbackID != null) + return false; + } else if (!callbackID.equals(other.callbackID)) + return false; + if (callbackObjectID == null) { + if (other.callbackObjectID != null) + return false; + } else if (!callbackObjectID.equals(other.callbackObjectID)) + return false; + if (callbackReference == null) { + if (other.callbackReference != null) + return false; + } else if (!callbackReference.equals(other.callbackReference)) + return false; + + return true; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java new file mode 100644 index 0000000000..6032005b9a --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.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.sca.core.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.impl.ComponentImpl; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ResolverExtension; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class RuntimeComponentImpl extends ComponentImpl implements RuntimeComponent, + ScopedRuntimeComponent, ResolverExtension { + protected RuntimeComponentContext componentContext; + protected ImplementationProvider implementationProvider; + protected List policyProviders = new ArrayList(); + protected ScopeContainer scopeContainer; + protected boolean started; + protected ModelResolver modelResolver; + + /** + */ + public RuntimeComponentImpl() { + super(); + } + + public ImplementationProvider getImplementationProvider() { + return implementationProvider; + } + + public void setImplementationProvider(ImplementationProvider provider) { + this.implementationProvider = provider; + } + + public ScopeContainer getScopeContainer() { + return scopeContainer; + } + + public void setScopeContainer(ScopeContainer scopeContainer) { + this.scopeContainer = scopeContainer; + } + + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + /** + * @return the componentContext + */ + public RuntimeComponentContext getComponentContext() { + return componentContext; + } + + /** + * @param componentContext the componentContext to set + */ + public void setComponentContext(RuntimeComponentContext componentContext) { + this.componentContext = componentContext; + } + + public void addPolicyProvider(PolicyProvider policyProvider) { + policyProviders.add(policyProvider); + } + + public List getPolicyProviders() { + return policyProviders; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java new file mode 100644 index 0000000000..3fdc35a720 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +/** + * Implementation of a Component Reference. + * + * @version $Rev$ $Date$ + */ +public class RuntimeComponentReferenceImpl extends ComponentReferenceImpl implements RuntimeComponentReference { + private ArrayList wires; + private HashMap bindingProviders = + new HashMap(); + private HashMap> policyProviders = new HashMap>(); + + private RuntimeComponent component; + + public RuntimeComponentReferenceImpl() { + super(); + } + + public synchronized List getRuntimeWires() { + if (wires == null) { + wires = new ArrayList(); + component.getComponentContext().start(this); + } + return wires; + } + + // TODO - EPR - shouldn't rely on this anymore + public RuntimeWire getRuntimeWire(Binding binding) { + for (RuntimeWire wire : getRuntimeWires()) { + if (wire.getEndpointReference().getBinding() == binding) { + return wire; + } + } + + return null; + } + + public RuntimeWire getRuntimeWire(EndpointReference endpointReference) { + for (RuntimeWire wire : getRuntimeWires()) { + if (wire.getEndpointReference() == endpointReference) { + return wire; + } + } + + return null; + } + + public ReferenceBindingProvider getBindingProvider(Binding binding) { + return bindingProviders.get(binding); + } + + public void setBindingProvider(Binding binding, ReferenceBindingProvider bindingProvider) { + bindingProviders.put(binding, bindingProvider); + } + + public Invoker getInvoker(Binding binding, Operation operation) { + RuntimeWire wire = getRuntimeWire(binding); + if (wire == null) { + return null; + } + InvocationChain chain = wire.getInvocationChain(operation); + return chain == null ? null : chain.getHeadInvoker(); + } + + /** + * @return the component + */ + public RuntimeComponent getComponent() { + return component; + } + + /** + * @param component the component to set + */ + public void setComponent(RuntimeComponent component) { + this.component = component; + } + + /** + * @see org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeComponentReferenceImpl ref = (RuntimeComponentReferenceImpl)super.clone(); + ref.wires = null; + ref.bindingProviders = new HashMap(); + ref.policyProviders = new HashMap>(); + return ref; + } + + public void addPolicyProvider(Binding binding, PolicyProvider policyProvider) { + List providers = policyProviders.get(binding); + if (providers == null) { + providers = new ArrayList(); + policyProviders.put(binding, providers); + } + providers.add(policyProvider); + } + + public List getPolicyProviders(Binding binding) { + List providers = policyProviders.get(binding); + if (providers == null) { + return Collections.emptyList(); + } else { + return providers; + } + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java new file mode 100644 index 0000000000..ffa488b7bd --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Implementation of a Component Service. + * + * @version $Rev$ $Date$ + */ +public class RuntimeComponentServiceImpl extends ComponentServiceImpl implements RuntimeComponentService { + private ArrayList wires = new ArrayList(); + private ArrayList callbackWires = new ArrayList(); + private HashMap bindingProviders = new HashMap(); + private HashMap> policyProviders = new HashMap>(); + + public RuntimeComponentServiceImpl() { + super(); + } + + public List getRuntimeWires() { + return wires; + } + + public RuntimeWire getRuntimeWire(Binding binding) { + for (RuntimeWire wire : wires) { + if (wire.getEndpoint().getBinding() == binding) { + return wire; + } + } + return null; + } + + public RuntimeWire getRuntimeWire(Binding binding, InterfaceContract interfaceContract) { + RuntimeWire wire = getRuntimeWire(binding); + if (wire == null) { + return null; + } + if (interfaceContract != null && interfaceContract != wire.getEndpointReference().getInterfaceContract()) { + try { + // FIXME: [rfeng] We could avoid clone() using a better comparison of the two interface contracts + wire = (RuntimeWire)wire.clone(); + wire.getEndpointReference().setInterfaceContract(interfaceContract); + wire.rebuild(); + } catch (CloneNotSupportedException e) { + throw new ServiceRuntimeException(e); + } + } + + return wire; + } + + public List getCallbackWires() { + return callbackWires; + } + + public ServiceBindingProvider getBindingProvider(Binding binding) { + return bindingProviders.get(binding); + } + + public void setBindingProvider(Binding binding, ServiceBindingProvider bindingProvider) { + bindingProviders.put(binding, bindingProvider); + } + + public Invoker getInvoker(Binding binding, Operation operation) { + return getInvoker(binding, null, operation); + } + + public Invoker getInvoker(Binding binding, InterfaceContract interfaceContract, Operation operation) { + InvocationChain chain = getInvocationChain(binding, interfaceContract, operation); + if (chain != null) { + return chain.getHeadInvoker(); + } else { + return null; + } + } + + public InvocationChain getInvocationChain(Binding binding, InterfaceContract interfaceContract, Operation operation) { + RuntimeWire wire = getRuntimeWire(binding); + if (wire == null) { + return null; + } + if (interfaceContract != null && interfaceContract != wire.getEndpointReference().getInterfaceContract()) { + try { + // FIXME: [rfeng] We could avoid clone() using a better comparison of the two interface contracts + wire = (RuntimeWire)wire.clone(); + wire.getEndpointReference().setInterfaceContract(interfaceContract); + wire.rebuild(); + } catch (CloneNotSupportedException e) { + throw new ServiceRuntimeException(e); + } + } + return wire.getInvocationChain(operation); + } + + public InvocationChain getInvocationChain(Binding binding, Operation operation) { + return getInvocationChain(binding, null, operation); + } + + /** + * @see org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl#clone() + */ + @SuppressWarnings("unchecked") + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeComponentServiceImpl clone = (RuntimeComponentServiceImpl)super.clone(); + clone.bindingProviders = (HashMap)bindingProviders.clone(); + clone.wires = (ArrayList)wires.clone(); + clone.callbackWires = (ArrayList)callbackWires.clone(); + clone.policyProviders = (HashMap>)policyProviders.clone(); + return clone; + } + + public void addPolicyProvider(Binding binding, PolicyProvider policyProvider) { + List providers = policyProviders.get(binding); + if (providers == null) { + providers = new ArrayList(); + policyProviders.put(binding, providers); + } + providers.add(policyProvider); + } + + public List getPolicyProviders(Binding binding) { + List providers = policyProviders.get(binding); + if (providers == null) { + return Collections.emptyList(); + } else { + return providers; + } + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java new file mode 100644 index 0000000000..357d19091b --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.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.sca.core.assembly.impl; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +import org.apache.tuscany.sca.assembly.impl.EndpointImpl; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.runtime.EndpointSerializer; + +/** + * Runtime model for Endpoint that supports java serialization + */ +public class RuntimeEndpointImpl extends EndpointImpl implements Externalizable { + private EndpointSerializer serializer; + private String bindingURI; + private String xml; + + /** + * No-arg constructor for Java serilization + */ + public RuntimeEndpointImpl() { + super(null); + } + + public RuntimeEndpointImpl(ExtensionPointRegistry registry) { + super(registry); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.uri = in.readUTF(); + this.xml = in.readUTF(); + // Defer the loading to resolve(); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(getURI()); + out.writeUTF(getSerializer().write(this)); + } + + private synchronized EndpointSerializer getSerializer() { + if (serializer == null) { + if (registry != null) { + serializer = + registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(EndpointSerializer.class); + } else { + throw new IllegalStateException("No extension registry is set"); + } + } + return serializer; + } + + @Override + protected void reset() { + super.reset(); + this.xml = null; + } + + @Override + public void resolve() { + if (component == null && xml != null) { + try { + getSerializer().read(this, xml); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + super.resolve(); + } + + @Override + public void setExtensionPointRegistry(ExtensionPointRegistry registry) { + if (this.registry != registry) { + super.setExtensionPointRegistry(registry); + serializer = null; + } + // resolve(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java new file mode 100644 index 0000000000..2b1c85b95a --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.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.sca.core.assembly.impl; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +import org.apache.tuscany.sca.assembly.impl.EndpointReferenceImpl; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.runtime.EndpointSerializer; + +/** + * Runtime model for Endpoint that supports java serialization + */ +public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implements Externalizable { + private EndpointSerializer serializer; + private String xml; + + /** + * No-arg constructor for Java serilization + */ + public RuntimeEndpointReferenceImpl() { + super(null); + } + + public RuntimeEndpointReferenceImpl(ExtensionPointRegistry registry) { + super(registry); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.uri = in.readUTF(); + this.xml = in.readUTF(); + // Defer the loading to resolve(); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(getURI()); + out.writeUTF(getSerializer().write(this)); + } + + private synchronized EndpointSerializer getSerializer() { + if (serializer == null) { + if (registry != null) { + serializer = + registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(EndpointSerializer.class); + } else { + throw new IllegalStateException("No extension registry is set"); + } + } + return serializer; + } + + @Override + protected void reset() { + super.reset(); + this.xml = null; + } + + @Override + protected void resolve() { + if (component == null && xml != null) { + try { + getSerializer().read(this, xml); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + super.resolve(); + } + + @Override + public void setExtensionPointRegistry(ExtensionPointRegistry registry) { + if (this.registry != registry) { + super.setExtensionPointRegistry(registry); + serializer = null; + } + // resolve(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl.java new file mode 100644 index 0000000000..3284168aeb --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeWireImpl.java @@ -0,0 +1,787 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.RuntimeWireInvoker; +import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl; +import org.apache.tuscany.sca.core.invocation.impl.PhaseManager; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.PolicyProviderRRB; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.ReferenceBindingProviderRRB; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProviderRRB; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.SCARuntimeException; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class RuntimeWireImpl implements RuntimeWire { + + private CompositeContext compositeContext; + private ExtensionPointRegistry extensionPoints; + + private Boolean isReferenceWire = false; + private EndpointReference endpointReference; + private Endpoint endpoint; + + private transient RuntimeWireProcessor wireProcessor; + private transient InterfaceContractMapper interfaceContractMapper; + private transient WorkScheduler workScheduler; + private transient PhaseManager phaseManager; + private transient MessageFactory messageFactory; + private transient RuntimeWireInvoker invoker; + + // the following is a very simple cache that avoids re-cloning a wire + // when consecutive callbacks to the same endpoint are made + private Endpoint lastCallback; + private RuntimeWire cachedWire; + private boolean wireReserved; + private RuntimeWireImpl clonedFrom; + + private List chains; + private InvocationChain bindingInvocationChain; + + private EndpointReferenceBinder eprBinder; + private final ProviderFactoryExtensionPoint providerFactories; + + /** + * @param source + * @param target + * @param interfaceContractMapper + * @param workScheduler + * @param wireProcessor + * @param messageFactory + * @param conversationManager + */ + public RuntimeWireImpl(CompositeContext compositeContext, + boolean isReferenceWire, + EndpointReference endpointReference, + Endpoint endpoint, + InterfaceContractMapper interfaceContractMapper, + WorkScheduler workScheduler, + RuntimeWireProcessor wireProcessor, + MessageFactory messageFactory) { + super(); + this.compositeContext = compositeContext; + this.extensionPoints = compositeContext.getExtensionPointRegistry(); + this.isReferenceWire = isReferenceWire; + this.endpointReference = endpointReference; + this.endpoint = endpoint; + this.interfaceContractMapper = interfaceContractMapper; + this.workScheduler = workScheduler; + this.wireProcessor = wireProcessor; + this.messageFactory = messageFactory; + this.invoker = new RuntimeWireInvoker(this.messageFactory, this); + + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class); + this.phaseManager = utilities.getUtility(PhaseManager.class); + this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class); + } + + public RuntimeWireImpl(CompositeContext compositeContext, + boolean isReferenceWire, + EndpointReference endpointReference, + Endpoint endpoint) { + super(); + this.compositeContext = compositeContext; + this.extensionPoints = compositeContext.getExtensionPointRegistry(); + this.isReferenceWire = isReferenceWire; + this.endpointReference = endpointReference; + this.endpoint = endpoint; + + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + this.wireProcessor = new ExtensibleWireProcessor(extensionPoints.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); + FactoryExtensionPoint factories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.messageFactory = factories.getFactory(MessageFactory.class); + this.invoker = new RuntimeWireInvoker(this.messageFactory, this); + + this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class); + this.phaseManager = utilities.getUtility(PhaseManager.class); + this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class); + } + + public synchronized List getInvocationChains() { + if (chains == null) { + initInvocationChains(); + } + return chains; + } + + public synchronized InvocationChain getBindingInvocationChain() { + if (bindingInvocationChain == null) { + bindingInvocationChain = new InvocationChainImpl(null, null, isReferenceWire, phaseManager); + if (isReferenceWire) { + initReferenceBindingInvocationChains(); + } else { + initServiceBindingInvocationChains(); + } + } + return bindingInvocationChain; + } + + public InvocationChain getInvocationChain(Operation operation) { + for (InvocationChain chain : getInvocationChains()) { + Operation op = null; + if (isReferenceWire) { + op = chain.getSourceOperation(); + } else { + op = chain.getTargetOperation(); + } + if (interfaceContractMapper.isCompatible(operation, op, op.getInterface().isRemotable())) { + return chain; + } + } + return null; + } + + public Object invoke(Message msg) throws InvocationTargetException { + return getBindingInvocationChain().getHeadInvoker().invoke(msg); + } + + public Object invoke(Operation operation, Object[] args) throws InvocationTargetException { + Message msg = messageFactory.createMessage(); + msg.setBody(args); + return invoker.invoke(operation, msg); + } + + public Object invoke(Operation operation, Message msg) throws InvocationTargetException { + return invoker.invoke(operation, msg); + } + + /** + * Navigate the component/componentType inheritence chain to find the leaf contract + * @param contract + * @return + */ + private Contract getLeafContract(Contract contract) { + Contract prev = null; + Contract current = contract; + while (current != null) { + prev = current; + if (current instanceof ComponentReference) { + current = ((ComponentReference)current).getReference(); + } else if (current instanceof CompositeReference) { + current = ((CompositeReference)current).getPromotedReferences().get(0); + } else if (current instanceof ComponentService) { + current = ((ComponentService)current).getService(); + } else if (current instanceof CompositeService) { + current = ((CompositeService)current).getPromotedService(); + } else { + break; + } + if (current == null) { + return prev; + } + } + return current; + } + + private InterfaceContract getLeafInterfaceContract(EndpointReference epr) { + ComponentReference reference = epr.getReference(); + if (reference == null) { + return epr.getInterfaceContract(); + } + InterfaceContract interfaceContract = getLeafContract(reference).getInterfaceContract(); + if (interfaceContract == null) { + interfaceContract = epr.getInterfaceContract(); + } + return interfaceContract; + } + + private InterfaceContract getLeafInterfaceContract(Endpoint ep) { + ComponentService service = ep.getService(); + if (service == null) { + return ep.getInterfaceContract(); + } + InterfaceContract interfaceContract = getLeafContract(service).getInterfaceContract(); + if (interfaceContract == null) { + interfaceContract = ep.getInterfaceContract(); + } + return interfaceContract; + } + + /** + * Initialize the invocation chains + */ + private void initInvocationChains() { + chains = new ArrayList(); + InterfaceContract sourceContract = endpointReference.getInterfaceContract(); + // TODO - EPR why is this looking at the component types. The endpoint reference should have the right interface contract by this time + //InterfaceContract sourceContract = getLeafInterfaceContract(endpointReference); + + if (isReferenceWire) { + // It's the reference wire + resolveEndpointReference(); + + InterfaceContract targetContract = endpoint.getInterfaceContract(); + // TODO - EPR why is this looking at the component types. The endpoint should have the right interface contract by this time + //InterfaceContract targetContract = getLeafInterfaceContract(endpoint); + + RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference(); + Binding refBinding = endpointReference.getBinding(); + for (Operation operation : sourceContract.getInterface().getOperations()) { + Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation); + if (targetOperation == null) { + throw new ServiceRuntimeException("No matching operation for " + operation.getName() + + " is found in reference " + + endpointReference.getComponent().getURI() + + "#" + + reference.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true, phaseManager); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(reference, refBinding, chain); + } + chains.add(chain); + addReferenceBindingInterceptor(reference, refBinding, chain, operation); + } + + } else { + // It's the service wire + RuntimeComponentService service = (RuntimeComponentService)endpoint.getService(); + RuntimeComponent serviceComponent = (RuntimeComponent)endpoint.getComponent(); + Binding serviceBinding = endpoint.getBinding(); + //InterfaceContract targetContract = endpoint.getInterfaceContract(); + // TODO - EPR - why is this looking at the component types. The endpoint should have the right interface contract by this time + InterfaceContract targetContract = getLeafInterfaceContract(endpoint); + endpoint.setInterfaceContract(targetContract); + for (Operation operation : sourceContract.getInterface().getOperations()) { + Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation); + if (targetOperation == null) { + throw new ServiceRuntimeException("No matching operation for " + operation.getName() + + " is found in service " + + serviceComponent.getURI() + + "#" + + service.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, false, phaseManager); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(service, serviceBinding, chain); + } + addServiceBindingInterceptor(service, serviceBinding, chain, operation); + addImplementationInterceptor(serviceComponent, service, chain, targetOperation); + chains.add(chain); + } + + } + wireProcessor.process(this); + } + + + /** + * This code used to be in the activator but has moved here as + * the endpoint reference may not now be resolved until the wire + * is first used + */ + private void resolveEndpointReference(){ + boolean ok = eprBinder.bind(compositeContext.getEndpointRegistry(), endpointReference); + + if (!ok) { + throw new SCARuntimeException("Unable to bind " + endpointReference); + } + + // set the endpoint based on the resolved endpoint + endpoint = endpointReference.getTargetEndpoint(); + + RuntimeComponentReference runtimeRef = (RuntimeComponentReference)endpointReference.getReference(); + + if (runtimeRef.getBindingProvider(endpointReference.getBinding()) == null) { + addReferenceBindingProvider(endpointReference, + (RuntimeComponent)endpointReference.getComponent(), + runtimeRef, + endpointReference.getBinding()); + } + + // start the binding provider + final ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(endpointReference.getBinding()); + + if (bindingProvider != null) { + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + bindingProvider.start(); + return null; + } + }); + } + for (PolicyProvider policyProvider : runtimeRef.getPolicyProviders(endpointReference.getBinding())) { + policyProvider.start(); + } + + InterfaceContract bindingContract = getInterfaceContract(endpointReference.getReference(), endpointReference.getBinding()); + Endpoint endpoint = endpointReference.getTargetEndpoint(); + endpoint.setInterfaceContract(bindingContract); + } + + private ReferenceBindingProvider addReferenceBindingProvider( + EndpointReference endpointReference, + RuntimeComponent component, RuntimeComponentReference reference, + Binding binding) { + BindingProviderFactory providerFactory = (BindingProviderFactory) providerFactories + .getProviderFactory(binding.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ReferenceBindingProvider bindingProvider = providerFactory + .createReferenceBindingProvider(endpointReference); + if (bindingProvider != null) { + ((RuntimeComponentReference) reference).setBindingProvider( + binding, bindingProvider); + } + for (PolicyProviderFactory f : providerFactories + .getPolicyProviderFactories()) { + PolicyProvider policyProvider = f + .createReferencePolicyProvider(endpointReference); + if (policyProvider != null) { + reference.addPolicyProvider(binding, policyProvider); + } + } + + return bindingProvider; + } else { + throw new IllegalStateException( + "Provider factory not found for binding: " + + binding.getType()); + } + } + + private InterfaceContract getInterfaceContract(ComponentReference reference, Binding binding) { + InterfaceContract interfaceContract = reference.getInterfaceContract(); + if (interfaceContract == null) { + interfaceContract = endpoint.getInterfaceContract(); + } + ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding); + if (provider != null) { + InterfaceContract bindingContract = provider.getBindingInterfaceContract(); + if (bindingContract != null) { + interfaceContract = bindingContract; + } + } + return interfaceContract.makeUnidirectional(false); + } + + private void initReferenceBindingInvocationChains() { + RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference(); + Binding referenceBinding = endpointReference.getBinding(); + + // add the binding interceptors to the reference binding wire + ReferenceBindingProvider provider = reference.getBindingProvider(referenceBinding); + if ((provider != null) && (provider instanceof ReferenceBindingProviderRRB)) { + ((ReferenceBindingProviderRRB)provider).configureBindingChain(this); + } + + // add the policy interceptors to the service binding wire + // find out which policies are active + List pps = ((RuntimeComponentReference)reference).getPolicyProviders(referenceBinding); + if (pps != null) { + for (PolicyProvider p : pps) { + if (p instanceof PolicyProviderRRB) { + Interceptor interceptor = ((PolicyProviderRRB)p).createBindingInterceptor(); + if (interceptor != null) { + bindingInvocationChain.addInterceptor(interceptor); + } + } + } + } + } + + private void initServiceBindingInvocationChains() { + RuntimeComponentService service = (RuntimeComponentService)endpoint.getService(); + Binding serviceBinding = endpoint.getBinding(); + + // add the binding interceptors to the service binding wire + ServiceBindingProvider provider = service.getBindingProvider(serviceBinding); + if ((provider != null) && (provider instanceof ServiceBindingProviderRRB)) { + ((ServiceBindingProviderRRB)provider).configureBindingChain(this); + } + + // add the policy interceptors to the service binding wire + List pps = ((RuntimeComponentService)service).getPolicyProviders(serviceBinding); + if (pps != null) { + for (PolicyProvider p : pps) { + if (p instanceof PolicyProviderRRB) { + Interceptor interceptor = ((PolicyProviderRRB)p).createBindingInterceptor(); + if (interceptor != null) { + bindingInvocationChain.addInterceptor(interceptor); + } + } + } + } + + // TODO - add something on the end of the wire to invoke the + // invocation chain. Need to split out the runtime + // wire invoker into conversation, callback interceptors etc + bindingInvocationChain.addInvoker(invoker); + + } + + // =============================================================== + // TODO - EPR remove when we convert fully over to EndpointReference2 + + // TODO - remove. Just here during development +/* + static EndpointReference epr; + + public EndpointReference getSource() { + // TODO - EPR convert this into method that returns EndpointReference2 + + // convert the source info into old endpoint reference format + epr = + new EndpointReferenceImpl((RuntimeComponent)endpointReference.getComponent(), endpointReference + .getReference(), endpointReference.getBinding(), endpointReference.getInterfaceContract()); + + if (endpointReference.getCallbackEndpoint() != null) { + // convert the source callback endpoint into old endpoint reference format + EndpointReference cepr; + cepr = + new EndpointReferenceImpl((RuntimeComponent)endpointReference.getComponent(), endpointReference + .getCallbackEndpoint().getService(), endpointReference.getCallbackEndpoint().getBinding(), + endpointReference.getCallbackEndpoint().getInterfaceContract()); + epr.setCallbackEndpoint(cepr); + } + + // TODO - somtimes used to reset the interface contract so we + // copy it back in in the rebuild method below + return epr; + } + + public EndpointReference getTarget() { + // TODO - EPR convert this into method that returns Endpoint2 + + Endpoint2 endpoint = this.endpoint != null ? this.endpoint : endpointReference.getTargetEndpoint(); + + // convert the target info into old endpoint reference format + EndpointReference epr = + new EndpointReferenceImpl((RuntimeComponent)endpoint.getComponent(), endpoint.getService(), endpoint + .getBinding(), endpoint.getInterfaceContract()); + return epr; + } + + public void setTarget(EndpointReference target) { + // TODO - can we use the idea of setTarget to rebuild the wire? + + } +*/ + + // =================================================================== + + public void rebuild() { + // TODO - can we use the idea of setTarget to rebuild the wire? + // used at the moment by binding.sca when it resets the + // source interface contract for local wires + this.chains = null; + + this.endpointReference.setStatus(EndpointReference.NOT_CONFIGURED); + + // TODO - cheating here as I fixed the RuntimeComponentService code + // to call this when it resets the interface contract + //endpointReference.setInterfaceContract(epr.getInterfaceContract()); + } + + public EndpointReference getEndpointReference() { + return endpointReference; + } + + public Endpoint getEndpoint() { + return endpoint; + } + + /** + * Add the interceptor for a reference binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addReferenceBindingInterceptor(ComponentReference reference, + Binding binding, + InvocationChain chain, + Operation operation) { + ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding); + if (provider != null) { + Invoker invoker = provider.createInvoker(operation); + if (invoker != null) { + chain.addInvoker(invoker); + } + } + List pps = ((RuntimeComponentReference)reference).getPolicyProviders(binding); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(p.createInterceptor(operation)); + } + } + } + } + + /** + * Add the interceptor for a binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addServiceBindingInterceptor(ComponentService service, + Binding binding, + InvocationChain chain, + Operation operation) { + List pps = ((RuntimeComponentService)service).getPolicyProviders(binding); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(p.createInterceptor(operation)); + } + } + } + } + + /** + * Add a non-blocking interceptor if the reference binding needs it + * + * @param reference + * @param binding + * @param chain + */ + private void addNonBlockingInterceptor(ComponentReference reference, Binding binding, InvocationChain chain) { + ReferenceBindingProvider provider = ((RuntimeComponentReference)reference).getBindingProvider(binding); + if (provider != null) { + boolean supportsOneWayInvocation = provider.supportsOneWayInvocation(); + if (!supportsOneWayInvocation) { + chain.addInterceptor(Phase.REFERENCE, new NonBlockingInterceptor(workScheduler)); + } + } + } + + /** + * Add a non-blocking interceptor if the service binding needs it + * + * @param service + * @param binding + * @param chain + */ + private void addNonBlockingInterceptor(ComponentService service, Binding binding, InvocationChain chain) { + ServiceBindingProvider provider = ((RuntimeComponentService)service).getBindingProvider(binding); + if (provider != null) { + if (!provider.supportsOneWayInvocation()) { + chain.addInterceptor(Phase.SERVICE, new NonBlockingInterceptor(workScheduler)); + } + } + } + + /** + * Add the interceptor for a component implementation + * + * @param component + * @param service + * @param chain + * @param operation + */ + private void addImplementationInterceptor(Component component, + ComponentService service, + InvocationChain chain, + Operation operation) { + + + + if (service.getService() instanceof CompositeService){ + CompositeService compositeService = (CompositeService)service.getService(); + component = getPromotedComponent(compositeService); + service = getPromotedComponentService(compositeService); + } + + ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider(); + + if (provider != null) { + Invoker invoker = null; + invoker = provider.createInvoker((RuntimeComponentService)service, operation); + chain.addInvoker(invoker); + } + // TODO - EPR - don't we need to get the policy from the right level in the + // model rather than the leafmost level + List pps = ((RuntimeComponent)component).getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(p.createInterceptor(operation)); + } + } + } + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeWireImpl copy = (RuntimeWireImpl)super.clone(); + copy.endpointReference = (EndpointReference)endpointReference.clone(); + copy.endpoint = copy.endpointReference.getTargetEndpoint(); + copy.invoker = new RuntimeWireInvoker(copy.messageFactory, copy); + copy.cachedWire = null; // TUSCANY-2630 + return copy; + } + + public synchronized RuntimeWire lookupCache(Endpoint callback) { + if (lastCallback != null && + callback.getURI().equals(lastCallback.getURI()) && + !wireReserved) { + wireReserved = true; + return cachedWire; + } else { + return null; + } + } + + public synchronized void addToCache(Endpoint callback, RuntimeWire clonedWire) { + ((RuntimeWireImpl)clonedWire).setClonedFrom(this); + lastCallback = callback; + cachedWire = clonedWire; + wireReserved = true; + } + + public synchronized void releaseClonedWire(RuntimeWire wire) { + if (cachedWire == wire) { + wireReserved = false; + } + } + + public synchronized void releaseWire() { + clonedFrom.releaseClonedWire(this); + } + + private void setClonedFrom(RuntimeWireImpl wire) { + clonedFrom = wire; + } + + public ExtensionPointRegistry getExtensionPoints() { + return extensionPoints; + } + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + private ComponentService getPromotedComponentService(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponentService((CompositeService)service); + + } else { + + // Found a non-composite service + return componentService; + } + } else { + + // No promoted service + return null; + } + } + + /** + * Follow a service promotion chain down to the innermost (non-composite) component. + * + * @param compositeService + * @return + */ + private Component getPromotedComponent(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponent((CompositeService)service); + + } else { + + // Found a non-composite service + return compositeService.getPromotedComponent(); + } + } else { + + // No promoted service + return null; + } + } + + public boolean isOutOfDate() { + return eprBinder.isOutOfDate(compositeContext.getEndpointRegistry(), getEndpointReference()); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java new file mode 100644 index 0000000000..2de52bebb2 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.context; + +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.context.impl.ComponentContextImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class DefaultComponentContextFactory implements ComponentContextFactory { + private final ExtensionPointRegistry registry; + + public DefaultComponentContextFactory(ExtensionPointRegistry registry) { + this.registry = registry; + } + + public ComponentContext createComponentContext(CompositeContext compositeContext, RuntimeComponent component) { + return new ComponentContextImpl(registry, compositeContext, component); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java new file mode 100644 index 0000000000..ace4dc48e1 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.context; + +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.context.impl.RequestContextImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.RequestContext; + +/** + * Default implementation of RequestContextFactory + */ +public class DefaultRequestContextFactory implements RequestContextFactory { + + public DefaultRequestContextFactory(ExtensionPointRegistry registry) { + } + + public RequestContext createRequestContext(RuntimeComponent component) { + return new RequestContextImpl(component); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java new file mode 100644 index 0000000000..9b60415132 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.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.sca.core.context; + +import java.io.Externalizable; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceReference; + +/** + * Extended ServiceReference + */ +public interface ServiceReferenceExt extends ServiceReference, Externalizable { + /** + * Return the wire that sits behind this service reference + * @return wire + */ + RuntimeWire getRuntimeWire(); + + /** + * Return the EndpointReference that sits behind this service reference + * @return endpoint reference + */ + EndpointReference getEndpointReference(); + + // TODO - EPR - the the following still required? + /** + * TBD + * + * @param callbackID + */ + void attachCallbackID(Object callbackID); + + /** + * TBD + * + * @return + */ + XMLStreamReader getXMLReader(); +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java new file mode 100644 index 0000000000..5218a7fd01 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.context.impl; + + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeWireImpl; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +public class CallbackServiceReferenceImpl extends ServiceReferenceImpl { + private RuntimeWire wire; + private List wires; + private Endpoint resolvedEndpoint; + + /* + * Public constructor for Externalizable serialization/deserialization + */ + public CallbackServiceReferenceImpl() { + super(); + } + + public CallbackServiceReferenceImpl(Class interfaze, List wires, ProxyFactory proxyFactory) { + super(interfaze, null, proxyFactory); + this.wires = wires; + init(); + } + + public void init() { + Message msgContext = ThreadMessageContext.getMessageContext(); + wire = selectCallbackWire(msgContext); + if (wire == null) { + //FIXME: need better exception + throw new RuntimeException("No callback binding found for " + msgContext.getTo().toString()); + } + resolvedEndpoint = msgContext.getFrom().getCallbackEndpoint(); + } + + @Override + protected Object createProxy() throws Exception { + return proxyFactory.createCallbackProxy(this); + } + + public RuntimeWire getCallbackWire() { + if (resolvedEndpoint == null) { + return null; + } else { + return cloneAndBind(wire); + } + } + + public Endpoint getResolvedEndpoint() { + return resolvedEndpoint; + } + + private RuntimeWire selectCallbackWire(Message msgContext) { + // look for callback binding with same name as service binding + Endpoint to = msgContext.getTo(); + if (to == null) { + //FIXME: need better exception + throw new RuntimeException("Destination for forward call is not available"); + } + for (RuntimeWire wire : wires) { + if (wire.getEndpointReference().getBinding().getName().equals(to.getBinding().getName())) { + return wire; + } + } + + // if no match, look for callback binding with same type as service binding + for (RuntimeWire wire : wires) { + if (wire.getEndpointReference().getBinding().getClass() == to.getBinding().getClass()) { + return wire; + } + } + + // no suitable callback wire was found + return null; + } + + private RuntimeWire cloneAndBind(RuntimeWire wire) { + RuntimeWire boundWire = null; + if (resolvedEndpoint != null) { + boundWire = ((RuntimeWireImpl)wire).lookupCache(resolvedEndpoint); + if (boundWire != null) { + return boundWire; + } + try { + // TODO - EPR - is this correct? + + // Fluff up a new response wire based on the callback endpoint + RuntimeComponentReference ref = + bind((RuntimeComponentReference)wire.getEndpointReference().getReference(), + resolvedEndpoint); + + boundWire = ref.getRuntimeWires().get(0); + + Binding binding = wire.getEndpointReference().getBinding(); + + ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire); + } catch (CloneNotSupportedException e) { + // will not happen + } + } + return boundWire; + } + + private RuntimeComponentReference bind(RuntimeComponentReference reference, + Endpoint callbackEndpoint) throws CloneNotSupportedException { + + // clone the callback reference ready to configure it for this callback endpoint + RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone(); + ref.getTargets().clear(); + ref.getBindings().clear(); + ref.getEndpointReferences().clear(); + + // no access to the assembly factory so clone an existing epr + EndpointReference callbackEndpointReference = (EndpointReference)reference.getEndpointReferences().get(0).clone(); + + callbackEndpointReference.setReference(ref); + callbackEndpointReference.setTargetEndpoint(callbackEndpoint); + callbackEndpointReference.setUnresolved(true); + + // TODO - should really use incoming callback info but awaiting + // decision from OASIS on what will happen with callbacks + // The callback endpoint will be resolved with the registry + // when the wire chains are created + ref.getEndpointReferences().add(callbackEndpointReference); + + return ref; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java new file mode 100644 index 0000000000..4e71181747 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java @@ -0,0 +1,496 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.context.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.apache.tuscany.sca.runtime.CompositeActivator; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.oasisopen.sca.RequestContext; +import org.oasisopen.sca.SCARuntimeException; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Implementation of ComponentContext that delegates to a ComponentContextProvider. + * + * @version $Rev$ $Date$ + */ +public class ComponentContextImpl implements RuntimeComponentContext { + private final RuntimeComponent component; + + private final CompositeContext compositeContext; + private final CompositeActivator compositeActivator; + private final RequestContextFactory requestContextFactory; + private final ProxyFactory proxyFactory; + private final AssemblyFactory assemblyFactory; + private final JavaInterfaceFactory javaInterfaceFactory; + private final PropertyValueFactory propertyFactory; + private final EndpointReferenceBinder eprBinder; + private final Monitor monitor; + + public ComponentContextImpl(ExtensionPointRegistry registry, CompositeContext compositeContext, RuntimeComponent component) { + this.component = component; + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.compositeContext = compositeContext; + + this.compositeActivator = utilities.getUtility(CompositeActivator.class); + + this.requestContextFactory = + registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class); + this.proxyFactory = new ExtensibleProxyFactory(registry.getExtensionPoint(ProxyFactoryExtensionPoint.class)); + this.propertyFactory = factories.getFactory(PropertyValueFactory.class); + + this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class); + + MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class); + this.monitor = monitorFactory.createMonitor(); + } + + public String getURI() { + return component.getURI(); + } + + public > R cast(B target) throws IllegalArgumentException { + return (R)proxyFactory.cast(target); + } + + public B getService(Class businessInterface, String referenceName) { + ServiceReference serviceRef = getServiceReference(businessInterface, referenceName); + return serviceRef.getService(); + } + + public ServiceReference getServiceReference(Class businessInterface, String referenceName) { + try { + for (ComponentReference ref : component.getReferences()) { + if (referenceName.equals(ref.getName())) { + /* ******************** Contribution for issue TUSCANY-2281 ******************** */ + Multiplicity multiplicity = ref.getMultiplicity(); + if (multiplicity == Multiplicity.ZERO_N || multiplicity == Multiplicity.ONE_N) { + throw new IllegalArgumentException("Reference " + referenceName + + " has multiplicity " + + multiplicity); + } + /* ******************** Contribution for issue TUSCANY-2281 ******************** */ + + return getServiceReference(businessInterface, (RuntimeComponentReference)ref, null); + } + } + throw new ServiceRuntimeException("Reference not found: " + referenceName); + } catch (ServiceRuntimeException e) { + throw e; + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + /** + * Gets the value for the specified property with the specified type. + * + * @param type The type of the property value we are getting + * @param propertyName The name of the property we are getting + * @param B The class of the property value we are getting + * + * @throws ServiceRuntimeException If a Property for the specified propertyName + * is not found + * + * @see #setPropertyValueFactory(PropertyValueFactory) + */ + public B getProperty(Class type, String propertyName) { + for (ComponentProperty p : component.getProperties()) { + if (propertyName.equals(p.getName())) { + return propertyFactory.createPropertyValue(p, type); + } + } + throw new ServiceRuntimeException("Property not found: " + propertyName); + } + + /** + * @param component + */ + public static ComponentService getSingleService(Component component) { + ComponentService targetService; + List services = component.getServices(); + List regularServices = new ArrayList(); + for (ComponentService service : services) { + if (service.isForCallback()) { + continue; + } + String name = service.getName(); + if (!name.startsWith("$") || name.startsWith("$dynamic$")) { + regularServices.add(service); + } + } + if (regularServices.size() == 0) { + throw new ServiceRuntimeException("No service is declared on component " + component.getURI()); + } + if (regularServices.size() != 1) { + throw new ServiceRuntimeException("More than one service is declared on component " + component.getURI() + + ". Service name is required to get the service."); + } + targetService = regularServices.get(0); + return targetService; + } + + + public ServiceReference createSelfReference(Class businessInterface) { + ComponentService service = getSingleService(component); + try { + return createSelfReference(businessInterface, service); + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + public ServiceReference createSelfReference(Class businessInterface, String serviceName) { + try { + for (ComponentService service : component.getServices()) { + if (serviceName.equals(service.getName())) { + return createSelfReference(businessInterface, service); + } + } + throw new ServiceRuntimeException("Service not found: " + serviceName); + } catch (ServiceRuntimeException e) { + throw e; + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + /** + * @param + * @param businessInterface + * @param service + * @return + */ + public ServiceReference createSelfReference(Class businessInterface, ComponentService service) { + try { + RuntimeComponentReference ref = + (RuntimeComponentReference)createSelfReference(component, service, businessInterface); + ref.setComponent(component); + return getServiceReference(businessInterface, ref, null); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public RequestContext getRequestContext() { + if (requestContextFactory != null) { + return requestContextFactory.createRequestContext(component); + } else { + return new RequestContextImpl(component); + } + } + + /** + * @param businessInterface + * @param reference + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + public ServiceReference getServiceReference(Class businessInterface, + RuntimeComponentReference reference, + EndpointReference endpointReference) { + try { + RuntimeComponentReference ref = (RuntimeComponentReference)reference; + InterfaceContract interfaceContract = reference.getInterfaceContract(); + Reference componentTypeReference = reference.getReference(); + if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) { + interfaceContract = componentTypeReference.getInterfaceContract(); + } + InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface); + if (refInterfaceContract != interfaceContract) { + ref = (RuntimeComponentReference)reference.clone(); + if (interfaceContract != null) { + ref.setInterfaceContract(interfaceContract); + } else { + ref.setInterfaceContract(refInterfaceContract); + } + } + ref.setComponent(component); + return new ServiceReferenceImpl(businessInterface, component, ref, endpointReference, proxyFactory, + component.getComponentContext().getCompositeContext()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Bind a component reference to a component service + * @param + * @param businessInterface + * @param reference + * @param service + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + public ServiceReference getServiceReference(Class businessInterface, + RuntimeComponentReference reference, + RuntimeComponent component, + RuntimeComponentService service) { + try { + RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone(); + InterfaceContract interfaceContract = reference.getInterfaceContract(); + Reference componentTypeReference = reference.getReference(); + if (componentTypeReference != null && componentTypeReference.getInterfaceContract() != null) { + interfaceContract = componentTypeReference.getInterfaceContract(); + } + InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface); + if (refInterfaceContract != interfaceContract) { + ref = (RuntimeComponentReference)reference.clone(); + ref.setInterfaceContract(interfaceContract); + } + ref.getTargets().add(service); + ref.getBindings().clear(); + for (Binding binding : service.getBindings()) { + if (binding instanceof OptimizableBinding) { + OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone(); + optimizableBinding.setTargetBinding(binding); + optimizableBinding.setTargetComponent(component); + optimizableBinding.setTargetComponentService(service); + ref.getBindings().add(optimizableBinding); + } else { + ref.getBindings().add(binding); + } + } + return new ServiceReferenceImpl(businessInterface, component, ref, null, proxyFactory, compositeContext); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public ServiceReference getCallableReference(Class businessInterface, + RuntimeComponent component, + RuntimeComponentService service) { + try { + if (businessInterface == null) { + InterfaceContract contract = service.getInterfaceContract(); + businessInterface = (Class)((JavaInterface)contract.getInterface()).getJavaClass(); + } + RuntimeComponentReference ref = + (RuntimeComponentReference)createSelfReference(component, service, businessInterface); + ref.setComponent(component); + return new ServiceReferenceImpl(businessInterface, component, ref, null, proxyFactory, + compositeContext); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Create a self-reference for a component service + * @param component + * @param service + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + private ComponentReference createSelfReference(Component component, + ComponentService service, + Class businessInterface) throws CloneNotSupportedException, + InvalidInterfaceException { + ComponentReference componentReference = assemblyFactory.createComponentReference(); + componentReference.setName("$self$." + service.getName()); + + for (Binding binding : service.getBindings()) { + if (binding instanceof OptimizableBinding) { + OptimizableBinding optimizableBinding = (OptimizableBinding)((OptimizableBinding)binding).clone(); + optimizableBinding.setTargetBinding(binding); + optimizableBinding.setTargetComponent(component); + optimizableBinding.setTargetComponentService(service); + componentReference.getBindings().add(optimizableBinding); + } else { + componentReference.getBindings().add(binding); + } + } + + componentReference.setCallback(service.getCallback()); + componentReference.getTargets().add(service); + componentReference.getPolicySets().addAll(service.getPolicySets()); + componentReference.getRequiredIntents().addAll(service.getRequiredIntents()); + + InterfaceContract interfaceContract = service.getInterfaceContract(); + Service componentTypeService = service.getService(); + if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) { + interfaceContract = componentTypeService.getInterfaceContract(); + } + interfaceContract = getInterfaceContract(interfaceContract, businessInterface); + componentReference.setInterfaceContract(interfaceContract); + componentReference.setMultiplicity(Multiplicity.ONE_ONE); + // component.getReferences().add(componentReference); + + // create endpoint reference + EndpointReference endpointReference = assemblyFactory + .createEndpointReference(); + endpointReference.setComponent(component); + endpointReference.setReference(componentReference); + endpointReference.setUnresolved(false); + endpointReference.setStatus(EndpointReference.WIRED_TARGET_FOUND_READY_FOR_MATCHING); + + // create endpoint. + Endpoint endpoint = assemblyFactory.createEndpoint(); + endpoint.setComponent(component); + endpoint.setService(service); + endpoint.setUnresolved(true); + endpointReference.setTargetEndpoint(endpoint); + + componentReference.getEndpointReferences().add(endpointReference); + + // do binding matching + boolean ok = eprBinder.bind(compositeContext.getEndpointRegistry(), endpointReference); + + if (!ok) { + throw new SCARuntimeException("Unable to bind " + endpointReference); + } + + return componentReference; + } + + /** + * @param interfaceContract + * @param businessInterface + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class businessInterface) + throws CloneNotSupportedException, InvalidInterfaceException { + boolean compatible = false; + if (interfaceContract != null && interfaceContract.getInterface() != null) { + Interface interfaze = interfaceContract.getInterface(); + if (interfaze instanceof JavaInterface) { + Class cls = ((JavaInterface)interfaze).getJavaClass(); + if (businessInterface.isAssignableFrom(cls)) { + compatible = true; + } + } + } + + if (!compatible) { + // The interface is not assignable from the interface contract + interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface); + interfaceContract.setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + interfaceContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(callInterface + .getCallbackClass())); + } + } + + return interfaceContract; + } + + /** + * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#start(org.apache.tuscany.sca.runtime.RuntimeComponentReference) + */ + public void start(RuntimeComponentReference reference) { + compositeActivator.start(compositeContext, component, reference); + } + + + /* ******************** Contribution for issue TUSCANY-2281 ******************** */ + + /** + * @see ComponentContext#getServices(Class, String) + */ + public Collection getServices(Class businessInterface, String referenceName) { + ArrayList services = new ArrayList(); + Collection> serviceRefs = getServiceReferences(businessInterface, referenceName); + for (ServiceReference serviceRef : serviceRefs) { + services.add(serviceRef.getService()); + } + return services; + } + + /** + * @see ComponentContext#getServiceReferences(Class, String) + */ + public Collection> getServiceReferences(Class businessInterface, String referenceName) { + try { + for (ComponentReference ref : component.getReferences()) { + if (referenceName.equals(ref.getName())) { + ArrayList> serviceRefs = new ArrayList>(); + for (EndpointReference endpointReference : ref.getEndpointReferences()) { + serviceRefs + .add(getServiceReference(businessInterface, (RuntimeComponentReference)ref, endpointReference)); + } + return serviceRefs; + } + } + throw new ServiceRuntimeException("Reference not found: " + referenceName); + } catch (ServiceRuntimeException e) { + throw e; + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + /* ******************** Contribution for issue TUSCANY-2281 ******************** */ + + public CompositeContext getCompositeContext() { + return compositeContext; + } + + public ExtensionPointRegistry getExtensionPointRegistry() { + return getCompositeContext().getExtensionPointRegistry(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java new file mode 100644 index 0000000000..e8a1254dc9 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.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.sca.core.context.impl; + +import java.util.List; + +import javax.security.auth.Subject; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.RequestContext; +import org.oasisopen.sca.ServiceReference; + +/** + * @version $Rev$ $Date$ + */ +public class RequestContextImpl implements RequestContext { + + private ProxyFactoryExtensionPoint proxyFactoryExtensionPoint; + + public RequestContextImpl(RuntimeComponent component) { + ExtensionPointRegistry registry = component.getComponentContext().getExtensionPointRegistry(); + proxyFactoryExtensionPoint = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + } + + public Subject getSecuritySubject() { + Subject subject = null; + + for (Object header : ThreadMessageContext.getMessageContext().getHeaders()){ + if (header instanceof Subject){ + subject = (Subject)header; + break; + } + } + return subject; + } + + public String getServiceName() { + return ThreadMessageContext.getMessageContext().getTo().getService().getName(); + } + + public ServiceReference getServiceReference() { + Message msgContext = ThreadMessageContext.getMessageContext(); + // FIXME: [rfeng] Is this the service reference matching the caller side? + Endpoint to = msgContext.getTo(); + RuntimeComponentService service = (RuntimeComponentService) to.getService(); + RuntimeComponent component = (RuntimeComponent) to.getComponent(); + + ServiceReference callableReference = component.getComponentContext().getCallableReference(null, component, service); + + //TODO - EPR - not required for OASIS + //ReferenceParameters parameters = msgContext.getFrom().getReferenceParameters(); + //((CallableReferenceExt) callableReference).attachCallbackID(parameters.getCallbackID()); + //((CallableReferenceExt) callableReference).attachConversation(parameters.getConversationID()); + + return callableReference; + } + + public CB getCallback() { + ServiceReference cb = getCallbackReference(); + if (cb == null) { + return null; + } + return cb.getService(); + } + + @SuppressWarnings("unchecked") + public ServiceReference getCallbackReference() { + Message msgContext = ThreadMessageContext.getMessageContext(); + Endpoint to = msgContext.getTo(); + RuntimeComponentService service = (RuntimeComponentService) to.getService(); + RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference(); + if (callbackReference == null) { + return null; + } + JavaInterface javaInterface = (JavaInterface) callbackReference.getInterfaceContract().getInterface(); + Class javaClass = (Class)javaInterface.getJavaClass(); + List wires = callbackReference.getRuntimeWires(); + ProxyFactory proxyFactory = new ExtensibleProxyFactory(proxyFactoryExtensionPoint); + ServiceReferenceImpl ref = new CallbackServiceReferenceImpl(javaClass, wires, proxyFactory); + if (ref != null) { + //ref.resolveTarget(); + // TODO - EPR - not required for OASIS + //ReferenceParameters parameters = msgContext.getFrom().getReferenceParameters(); + //ref.attachCallbackID(parameters.getCallbackID()); + //if (ref.getConversation() != null) { + // ref.attachConversationID(parameters.getConversationID()); + //} + } + return ref; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java new file mode 100644 index 0000000000..23126b5123 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java @@ -0,0 +1,481 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.context.impl; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.UUID; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.assembly.impl.ReferenceParametersImpl; +import org.apache.tuscany.sca.core.context.ServiceReferenceExt; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.ReferenceParameters; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Default implementation of a ServiceReference. + * + * @version $Rev$ $Date$ + * @param the type of the business interface + */ +public class ServiceReferenceImpl implements ServiceReferenceExt { + private static final long serialVersionUID = 6763709434194361540L; + + protected transient ProxyFactory proxyFactory; + protected transient Class businessInterface; + protected transient Object proxy; + + protected Object callbackID; // The callbackID should be serializable + + protected transient RuntimeComponent component; + protected transient RuntimeComponentReference reference; + protected transient EndpointReference endpointReference; + + protected String scdl; + + private transient XMLStreamReader xmlReader; + + protected transient CompositeContext compositeContext; + private ExtensionPointRegistry registry; + private FactoryExtensionPoint modelFactories; + protected RuntimeAssemblyFactory assemblyFactory; + private StAXArtifactProcessorExtensionPoint staxProcessors; + private StAXArtifactProcessor staxProcessor; + private XMLInputFactory xmlInputFactory; + private XMLOutputFactory xmlOutputFactory; + private BuilderExtensionPoint builders; + + /* + * Public constructor for Externalizable serialization/deserialization + */ + public ServiceReferenceImpl() { + super(); + } + + /* + * Public constructor for use by XMLStreamReader2CallableReference + */ + // TODO - EPR - Is this required + public ServiceReferenceImpl(XMLStreamReader xmlReader) throws Exception { + this.xmlReader = xmlReader; + resolve(); + } + + protected ServiceReferenceImpl(Class businessInterface, + RuntimeComponent component, + RuntimeComponentReference reference, + EndpointReference endpointReference, + ProxyFactory proxyFactory, + CompositeContext compositeContext) { + this.proxyFactory = proxyFactory; + this.businessInterface = businessInterface; + this.component = component; + this.reference = reference; + this.endpointReference = endpointReference; + this.compositeContext = compositeContext; + + getExtensions(); + + // FIXME: The SCA Specification is not clear how we should handle multiplicity + // for CallableReference + if (this.endpointReference == null) { + + // TODO - EPR - If no endpoint reference specified assume the first one + // This will happen when a self reference is created in which case the + // the reference should only have one endpointReference so use that + if (this.reference.getEndpointReferences().size() == 0){ + throw new ServiceRuntimeException("The reference " + reference.getName() + " in component " + + component.getName() + " has no endpoint references"); + } + + if (this.reference.getEndpointReferences().size() > 1){ + throw new ServiceRuntimeException("The reference " + reference.getName() + " in component " + + component.getName() + " has more than one endpoint reference"); + } + + this.endpointReference = this.reference.getEndpointReferences().get(0); + } + + // FIXME: Should we normalize the componentName/serviceName URI into an absolute SCA URI in the SCA binding? + // sca:component1/component11/component112/service1? + initCallbackID(); + } + + private void getExtensions() { + this.registry = compositeContext.getExtensionPointRegistry(); + this.modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + this.xmlInputFactory = modelFactories.getFactory(XMLInputFactory.class); + this.xmlOutputFactory = modelFactories.getFactory(XMLOutputFactory.class); + this.staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + this.staxProcessor = staxProcessors.getProcessor(EndpointReference.class); + this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + } + + public ServiceReferenceImpl(Class businessInterface, RuntimeWire wire, ProxyFactory proxyFactory) { + this.proxyFactory = proxyFactory; + this.businessInterface = businessInterface; + //ExtensionPointRegistry registry = ((RuntimeWireImpl)wire).getExtensionPoints(); + //this.modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + //this.assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + bind(wire); + } + + public RuntimeWire getRuntimeWire() { + try { + resolve(); + if (endpointReference != null){ + return reference.getRuntimeWire(endpointReference); + } else { + return null; + } + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public EndpointReference getEndpointReference() { + return endpointReference; + } + + protected void bind(RuntimeWire wire) { + if (wire != null) { + this.component = (RuntimeComponent)wire.getEndpointReference().getComponent(); + this.reference = (RuntimeComponentReference)wire.getEndpointReference().getReference(); + this.endpointReference = wire.getEndpointReference(); + this.compositeContext = component.getComponentContext().getCompositeContext(); + initCallbackID(); + } + } + + protected void initCallbackID() { + if (reference.getInterfaceContract() != null) { + if (reference.getInterfaceContract().getCallbackInterface() != null) { + this.callbackID = createCallbackID(); + } + } + } + + public B getProxy() throws ObjectCreationException { + try { + if (proxy == null) { + proxy = createProxy(); + } + return businessInterface.cast(proxy); + } catch (Exception e) { + throw new ObjectCreationException(e); + } + } + + public void setProxy(Object proxy) { + this.proxy = proxy; + } + + protected Object createProxy() throws Exception { + return proxyFactory.createProxy(this); + } + + public B getService() { + try { + resolve(); + return getProxy(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public Class getBusinessInterface() { + try { + resolve(); + return businessInterface; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public boolean isConversational() { + try { + resolve(); + return reference == null ? false : reference.getInterfaceContract().getInterface().isConversational(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public Object getCallbackID() { + try { + resolve(); + return callbackID; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + private ComponentService getPromotedComponentService(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponentService((CompositeService)service); + + } else { + + // Found a non-composite service + return componentService; + } + } else { + + // No promoted service + return null; + } + } + + // ============ WRITE AND READ THE REFERENCE TO EXTERNAL XML ======================== + + /** + * write the reference to a stream + * + * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput) + */ + public void writeExternal(ObjectOutput out) throws IOException { + try { + String xml = null; + if (scdl == null){ + xml = toXMLString(); + } else { + xml = scdl; + } + + if (xml == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + out.writeUTF(xml); + } + } catch (Exception e) { + // e.printStackTrace(); + throw new IOException(e.toString()); + } + } + + /** + * write the endpoint reference into an xml string + */ + public String toXMLString() throws IOException, XMLStreamException, ContributionWriteException{ + StringWriter writer = new StringWriter(); + XMLStreamWriter streamWriter = xmlOutputFactory.createXMLStreamWriter(writer); + staxProcessor.write(endpointReference, streamWriter, new ProcessorContext(registry)); + return writer.toString(); + } + + /** + * Read the reference from a stream + * + * @see java.io.Externalizable#readExternal(java.io.ObjectInput) + */ + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + final boolean hasSCDL = in.readBoolean(); + if (hasSCDL) { + this.scdl = in.readUTF(); + } else { + this.scdl = null; + } + } + + /** + * Read xml string into the endpoint reference + */ + public void fromXMLString() throws IOException, XMLStreamException, ContributionReadException { + + XMLStreamReader streamReader = xmlReader; + + if (scdl != null ){ + Reader reader = new StringReader(scdl); + + if (xmlInputFactory == null){ + // this is a reference being read from a external stream + // so set up enough of the reference in order to resolved the + // xml being read + this.compositeContext = CompositeContext.getCurrentCompositeContext(); + getExtensions(); + } + + streamReader = xmlInputFactory.createXMLStreamReader(reader); + } + + endpointReference = staxProcessor.read(streamReader, new ProcessorContext(registry)); + + // ok to GC + xmlReader = null; + scdl = null; + } + + /** + * @throws IOException + */ + private synchronized void resolve() throws Exception { + if ((scdl != null || xmlReader != null) && component == null && reference == null) { + fromXMLString(); + + this.component = (RuntimeComponent)endpointReference.getComponent(); + compositeContext.bindComponent(this.component); + + this.reference = (RuntimeComponentReference)endpointReference.getReference(); + this.reference.setComponent(this.component); + + ReferenceParameters parameters = null; + for (Object ext : reference.getExtensions()) { + if (ext instanceof ReferenceParameters) { + parameters = (ReferenceParameters)ext; + break; + } + } + + if (parameters != null) { + this.callbackID = parameters.getCallbackID(); + } + + Interface i = reference.getInterfaceContract().getInterface(); + if (i instanceof JavaInterface) { + JavaInterface javaInterface = (JavaInterface)i; + if (javaInterface.isUnresolved()) { + // Allow privileged access to get ClassLoader. Requires RuntimePermission in + // security policy. + ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + + javaInterface.setJavaClass(classLoader.loadClass(javaInterface.getName())); + JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext); + + javaInterfaceFactory.createJavaInterface(javaInterface, javaInterface.getJavaClass()); + //FIXME: If the interface needs XSDs to be loaded (e.g., for static SDO), + // this needs to be done here. We usually search for XSDs in the current + // contribution at resolve time. Is it possible to locate the current + // contribution at runtime? + } + this.businessInterface = (Class)javaInterface.getJavaClass(); + } + + Binding binding = endpointReference.getBinding(); + if (binding != null) { + BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType()); + if (bindingBuilder != null) { + BuilderContext context = new BuilderContext(registry); + bindingBuilder.build(component, reference, endpointReference.getBinding(), context); + } + } + + this.proxyFactory = getProxyFactory(this.compositeContext); + } else if (compositeContext == null) { + this.compositeContext = CompositeContext.getCurrentCompositeContext(); + if (this.compositeContext != null) { + this.proxyFactory = getProxyFactory(this.compositeContext); + } + } + } + + private JavaInterfaceFactory getJavaInterfaceFactory(CompositeContext compositeContext) { + ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint factories = extensionPointRegistry.getExtensionPoint(FactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + return javaInterfaceFactory; + } + + private ProxyFactory getProxyFactory(CompositeContext compositeContext) { + ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry(); + ProxyFactoryExtensionPoint proxyFactories = extensionPointRegistry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + return new ExtensibleProxyFactory(proxyFactories); + } + + // ================================================================================== + + /** + * Create a callback id + * + * @return the callback id + */ + private String createCallbackID() { + return UUID.randomUUID().toString(); + } + + public void attachCallbackID(Object callbackID) { + this.callbackID = callbackID; + } + + protected ReferenceParameters getReferenceParameters() { + ReferenceParameters parameters = new ReferenceParametersImpl(); + parameters.setCallbackID(callbackID); + return parameters; + } + + public XMLStreamReader getXMLReader() { + return xmlReader; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java new file mode 100644 index 0000000000..2371897dce --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.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.sca.core.factory; + +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; + + +/** + * Provides lifecycle management for an implementation instance associated with + * a component for use by the component's associated {@link org.apache.tuscany.sca.core.scope.ScopeContainer} + * + * @version $Rev$ $Date$ + */ +public interface InstanceWrapper { + + /** + * @return + */ + T getInstance(); + + /** + * @throws TargetInitializationException + */ + void start() throws TargetInitializationException; + + /** + * @throws TargetDestructionException + */ + void stop() throws TargetDestructionException; + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java new file mode 100644 index 0000000000..d35b27fd24 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.factory; + + +/** + * Denotes an error creating a new object instance + * + * @version $Rev$ $Date$ + */ +public class ObjectCreationException extends RuntimeException { + private static final long serialVersionUID = -6423113430265944499L; + + public ObjectCreationException() { + super(); + } + + public ObjectCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCreationException(String message) { + super(message); + } + + public ObjectCreationException(Throwable cause) { + super(cause); + } + +} + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java new file mode 100644 index 0000000000..3f64d2405b --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.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.sca.core.factory; + +/** + * Implementations create new instances of a particular type + * + * @version $Rev$ $Date$ + */ +public interface ObjectFactory { + + /** + * Return a instance of the type that this factory creates. + * + * @return a instance from this factory + */ + T getInstance() throws ObjectCreationException; + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java new file mode 100644 index 0000000000..d4fe266d44 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.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.sca.core.invocation; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.oasisopen.sca.ServiceReference; + +/** + * Uses a wire to return a CallableReference + * + * @version $Rev$ $Date$ + */ +public class CallableReferenceObjectFactory implements ObjectFactory> { + private Class businessInterface; + private RuntimeComponent component; + private RuntimeComponentReference reference; + private EndpointReference endpointReference; + + /** + * Constructor. + * + * To support the @Reference protected CallableReference ref; + * + * @param businessInterface the interface to inject + * @param component the component defining the reference to be injected + * @param reference the reference to be injected + * @param binding the binding for the reference + */ + public CallableReferenceObjectFactory(Class businessInterface, + RuntimeComponent component, + RuntimeComponentReference reference, + EndpointReference endpointReference) { + this.businessInterface = businessInterface; + this.component = component; + this.reference = reference; + this.endpointReference = endpointReference; + } + + public ServiceReference getInstance() throws ObjectCreationException { + return component.getComponentContext().getServiceReference(businessInterface, reference, endpointReference); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java new file mode 100644 index 0000000000..588eaa2d15 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/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.sca.core.invocation; + +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + +/** + * An interceptor applied to the forward direction of a wire that ensures the callback target implements the required + * service contract. This is required as callback targets may be set dynamically by service implementations. + * + * @version $Rev$ $Date$ + */ +public class CallbackInterfaceInterceptor implements Interceptor { + private Invoker next; + + public CallbackInterfaceInterceptor() { + } + + public Message invoke(Message msg) { + + /* TODO - EPR - not required for OASIS + ReferenceParameters parameters = msg.getFrom().getReferenceParameters(); + if (parameters.getCallbackObjectID() != null || parameters.getCallbackReference() != msg.getFrom() + .getCallbackEndpoint()) { + */ + return next.invoke(msg); + /* + } else { + throw new NoRegisteredCallbackException("Callback target does not implement the callback interface"); + } + */ + } + + public void setNext(Invoker next) { + this.next = next; + } + + public Invoker getNext() { + return next; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java new file mode 100644 index 0000000000..021d588cb4 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.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.sca.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl; +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceReference; + +/** + * Uses a wire to return a CallableReference + * + * @version $Rev$ $Date$ + */ +public class CallbackReferenceObjectFactory implements ObjectFactory> { + private Class businessInterface; + private ProxyFactory proxyFactory; + private List wires; + + public CallbackReferenceObjectFactory(Class interfaze, ProxyFactory proxyFactory, List wires) { + this.businessInterface = interfaze; + this.proxyFactory = proxyFactory; + this.wires = wires; + } + + public ServiceReference getInstance() throws ObjectCreationException { + return new CallbackServiceReferenceImpl(businessInterface, wires, proxyFactory); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java new file mode 100644 index 0000000000..2b37c30451 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/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.sca.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +/** + * Returns proxy instance for a wire callback + * + * @version $Rev$ $Date$ + */ +public class CallbackWireObjectFactory implements ObjectFactory { + private Class businessInterface; + private ProxyFactory proxyFactory; + private List wires; + + public CallbackWireObjectFactory(Class interfaze, ProxyFactory proxyFactory, List wires) { + this.businessInterface = interfaze; + this.proxyFactory = proxyFactory; + this.wires = wires; + } + + public B getInstance() throws ObjectCreationException { + return proxyFactory.createCallbackProxy(businessInterface, wires); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java new file mode 100644 index 0000000000..11edc283a4 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation; + +import java.lang.reflect.Method; +import java.util.List; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.Factory; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.invocation.impl.JDKCallbackInvocationHandler; +import org.apache.tuscany.sca.core.invocation.impl.JDKInvocationHandler; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceReference; + +/** + * The implementation of a wire service that uses cglib dynamic proxies + * + * @version $Rev$ $Date$ + */ +public class CglibProxyFactory implements ProxyFactory { + private MessageFactory messageFactory; + + public CglibProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.messageFactory = messageFactory; + + } + + public T createProxy(Class interfaze, RuntimeWire wire) throws ProxyCreationException { + ServiceReference serviceReference = new ServiceReferenceImpl(interfaze, wire, this); + return createProxy(serviceReference); + } + + /** + * create the proxy with cglib. use the same JDKInvocationHandler as + * JDKProxyService. + */ + public T createProxy(ServiceReference callableReference) throws ProxyCreationException { + Enhancer enhancer = new Enhancer(); + Class interfaze = callableReference.getBusinessInterface(); + enhancer.setSuperclass(interfaze); + enhancer.setCallback(new CglibMethodInterceptor(callableReference)); + Object proxy = enhancer.create(); + ((ServiceReferenceImpl)callableReference).setProxy(proxy); + return interfaze.cast(proxy); + } + + /** + * create the callback proxy with cglib. use the same + * JDKCallbackInvocationHandler as JDKProxyService. + */ + public T createCallbackProxy(Class interfaze, final List wires) throws ProxyCreationException { + ServiceReferenceImpl callbackReference = new ServiceReferenceImpl(interfaze, wires.get(0), this); + return callbackReference != null ? createCallbackProxy(callbackReference) : null; + } + + /** + * create the callback proxy with cglib. use the same + * JDKCallbackInvocationHandler as JDKProxyService. + */ + public T createCallbackProxy(ServiceReferenceImpl callbackReference) throws ProxyCreationException { + Enhancer enhancer = new Enhancer(); + Class interfaze = callbackReference.getBusinessInterface(); + enhancer.setSuperclass(interfaze); + enhancer.setCallback(new CglibMethodInterceptor(callbackReference)); + Object proxy = enhancer.create(); + callbackReference.setProxy(proxy); + return interfaze.cast(proxy); + } + + @SuppressWarnings("unchecked") + public > R cast(B target) throws IllegalArgumentException { + if (isProxyClass(target.getClass())) { + Factory factory = (Factory)target; + Callback[] callbacks = factory.getCallbacks(); + if (callbacks.length != 1 || !(callbacks[0] instanceof CglibMethodInterceptor)) { + throw new IllegalArgumentException("The object is not a known proxy."); + } + CglibMethodInterceptor interceptor = (CglibMethodInterceptor)callbacks[0]; + return (R)interceptor.invocationHandler.getCallableReference(); + } else { + throw new IllegalArgumentException("The object is not a known proxy."); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class) + */ + public boolean isProxyClass(Class clazz) { + return Factory.class.isAssignableFrom(clazz); + } + + private class CglibMethodInterceptor implements MethodInterceptor { + private JDKInvocationHandler invocationHandler; + + public CglibMethodInterceptor(ServiceReference callableReference) { + invocationHandler = new JDKInvocationHandler(messageFactory, callableReference); + } + + public CglibMethodInterceptor(ServiceReferenceImpl callbackReference) { + invocationHandler = new JDKCallbackInvocationHandler(messageFactory, callbackReference); + } + + /* + public CglibMethodInterceptor(Class interfaze, RuntimeWire wire) { + ServiceReference serviceRef = new ServiceReferenceImpl(interfaze, wire, CglibProxyFactory.this); + invocationHandler = new JDKInvocationHandler(messageFactory, serviceRef); + } + + public CglibMethodInterceptor(Class interfaze, List wires) { + CallbackReferenceImpl ref = new CallbackReferenceImpl(interfaze, CglibProxyFactory.this, wires); + invocationHandler = new JDKCallbackInvocationHandler(messageFactory, ref); + } + */ + + /** + * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy) + */ + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + Object result = invocationHandler.invoke(proxy, method, args); + return result; + } + + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java new file mode 100644 index 0000000000..af6f039775 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.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.sca.core.invocation; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.impl.JDKProxyFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; + +/** + * Default implementation of a ProxyFactoryExtensionPoint. + * + * @version $Rev$ $Date$ + */ +public class DefaultProxyFactoryExtensionPoint implements ProxyFactoryExtensionPoint, LifeCycleListener { + private InterfaceContractMapper interfaceContractMapper; + private MessageFactory messageFactory; + + private ProxyFactory interfaceFactory; + private ProxyFactory classFactory; + + public DefaultProxyFactoryExtensionPoint(ExtensionPointRegistry extensionPoints) { + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + + FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.messageFactory = modelFactories.getFactory(MessageFactory.class); + + interfaceFactory = new JDKProxyFactory(messageFactory, interfaceContractMapper); + } + + public DefaultProxyFactoryExtensionPoint(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.interfaceContractMapper = mapper; + this.messageFactory = messageFactory; + interfaceFactory = new JDKProxyFactory(messageFactory, mapper); + } + + public ProxyFactory getClassProxyFactory() { + return classFactory; + } + + public ProxyFactory getInterfaceProxyFactory() { + return interfaceFactory; + } + + public void setClassProxyFactory(ProxyFactory factory) { + this.classFactory = factory; + + } + + public void setInterfaceProxyFactory(ProxyFactory factory) { + this.interfaceFactory = factory; + + } + + public void start() { + if (interfaceFactory instanceof LifeCycleListener) { + ((LifeCycleListener)interfaceFactory).start(); + } + if (classFactory instanceof LifeCycleListener) { + ((LifeCycleListener)classFactory).start(); + } + } + + public void stop() { + if (interfaceFactory instanceof LifeCycleListener) { + ((LifeCycleListener)interfaceFactory).stop(); + } + if (classFactory instanceof LifeCycleListener) { + ((LifeCycleListener)classFactory).stop(); + } + + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java new file mode 100644 index 0000000000..fbdfe8a8e6 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.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.sca.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceReference; + +/** + * An extensible proxy factory. + * + * @version $Rev$ $Date$ + */ +public class ExtensibleProxyFactory implements ProxyFactory { + + private ProxyFactoryExtensionPoint proxyFactories; + + public ExtensibleProxyFactory(ProxyFactoryExtensionPoint proxyFactories) { + this.proxyFactories = proxyFactories; + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#cast(java.lang.Object) + */ + @SuppressWarnings("unchecked") + public > R cast(B target) throws IllegalArgumentException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (interfaceFactory.isProxyClass(target.getClass())) { + return (R)interfaceFactory.cast(target); + } else if (classFactory != null && classFactory.isProxyClass(target.getClass())) { + return (R)classFactory.cast(target); + } else { + throw new IllegalArgumentException("The target is not a callable proxy"); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#createCallbackProxy(java.lang.Class, + * java.util.List) + */ + public T createCallbackProxy(Class interfaze, List wires) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (interfaze.isInterface()) { + return interfaceFactory.createCallbackProxy(interfaze, wires); + } else { + return classFactory.createCallbackProxy(interfaze, wires); + } + } + + public T createProxy(ServiceReference callableReference) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (callableReference.getBusinessInterface().isInterface()) { + return interfaceFactory.createProxy(callableReference); + } else { + return classFactory.createProxy(callableReference); + } + } + + public T createCallbackProxy(ServiceReferenceImpl callbackReference) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (callbackReference.getBusinessInterface().isInterface()) { + return interfaceFactory.createCallbackProxy(callbackReference); + } else { + return classFactory.createCallbackProxy(callbackReference); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#createProxy(java.lang.Class, + * org.apache.tuscany.sca.runtime.RuntimeWire) + */ + public T createProxy(Class interfaze, RuntimeWire wire) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (interfaze.isInterface()) { + return interfaceFactory.createProxy(interfaze, wire); + } else { + return classFactory.createProxy(interfaze, wire); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class) + */ + public boolean isProxyClass(Class clazz) { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + return interfaceFactory.isProxyClass(clazz) || (classFactory != null && classFactory.isProxyClass(clazz)); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java new file mode 100644 index 0000000000..934f2f7aa0 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; + +/** + * The default implementation of an extensible WireProcessor + * + * @version $Rev$ $Date$ + */ +public class ExtensibleWireProcessor implements RuntimeWireProcessor { + + private RuntimeWireProcessorExtensionPoint processors; + + public ExtensibleWireProcessor(RuntimeWireProcessorExtensionPoint processors) { + this.processors = processors; + } + + public void process(RuntimeWire wire) { + for (RuntimeWireProcessor processor : processors.getWireProcessors()) { + processor.process(wire); + } + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java new file mode 100644 index 0000000000..ec2f0a0664 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Adds non-blocking behavior to an invocation chain + * + * @version $Rev$ $Date$ + */ +public class NonBlockingInterceptor implements Interceptor { + + private static final Message RESPONSE = new ImmutableMessage(); + + /** + * The JDK logger that will be used to log messages. + */ + private static final Logger LOGGER = Logger.getLogger(NonBlockingInterceptor.class.getName()); + + private WorkScheduler workScheduler; + private Invoker next; + + public NonBlockingInterceptor(WorkScheduler workScheduler) { + this.workScheduler = workScheduler; + } + + public NonBlockingInterceptor(WorkScheduler workScheduler, Interceptor next) { + this.workScheduler = workScheduler; + this.next = next; + } + + /** + * Sets desired workScheduler to NonBlockingInterceptor. This is a useful function for the extension framework + * to set desired workmanager on the InvocationChain, other than default workmanager which is set per Tuscany runtime. + * Using this function, extension framework can set desired workmanager on InvocationChain during post wire processing. + * @param workScheduler workScheduler which contains workmanager + */ + public void setWorkScheduler(WorkScheduler workScheduler){ + this.workScheduler = workScheduler; + } + + public Message invoke(final Message msg) { + // Schedule the invocation of the next interceptor in a new Work instance + try { + workScheduler.scheduleWork(new Runnable() { + public void run() { + Message context = ThreadMessageContext.setMessageContext(msg); + try { + Message response = null; + + Throwable ex = null; + try { + response = next.invoke(msg); + } catch (Throwable t) { + ex = t; + } + + // Tuscany-2225 - Did the @OneWay method complete successfully? + // (i.e. no exceptions) + if (response != null && response.isFault()) { + // The @OneWay method threw an Exception. Lets log it and + // then pass it on to the WorkScheduler so it can notify any + // listeners + ex = (Throwable)response.getBody(); + } + if (ex != null) { + LOGGER.log(Level.SEVERE, "Exception from @OneWay invocation", ex); + throw new ServiceRuntimeException("Exception from @OneWay invocation", ex); + } + } finally { + ThreadMessageContext.setMessageContext(context); + } + } + }); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + return RESPONSE; + } + + public Invoker getNext() { + return next; + } + + public void setNext(Invoker next) { + this.next = next; + } + + /** + * 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 setCallbackWires(LinkedList wires) { + + } + + public Object getMessageID() { + return null; + } + + public void setMessageID(Object messageId) { + throw new UnsupportedOperationException(); + } + + public boolean isFault() { + return false; + } + + public void setFaultBody(Object fault) { + throw new UnsupportedOperationException(); + } + + public EndpointReference getFrom() { + return null; + } + + public Endpoint getTo() { + return null; + } + + public void setFrom(EndpointReference from) { + throw new UnsupportedOperationException(); + } + + public void setTo(Endpoint to) { + throw new UnsupportedOperationException(); + } + + public Operation getOperation() { + return null; + } + + public void setOperation(Operation op) { + throw new UnsupportedOperationException(); + } + + /** + * @see org.apache.tuscany.sca.invocation.Message#getReplyTo() + */ + public EndpointReference getReplyTo() { + return null; + } + + public Map getQoSContext() { + return null; + } + + public List getHeaders() { + return null; + } + public T getBindingContext() { + return null; + } + + public void setBindingContext(T bindingContext) { + } + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java new file mode 100644 index 0000000000..0b36b178f3 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.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.sca.core.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + + +/** + * Denotes an error creating a proxy + * + * @version $Rev$ $Date$ + */ +public class ProxyCreationException extends ObjectCreationException { + private static final long serialVersionUID = 8002454344828513781L; + + public ProxyCreationException() { + super(); + } + + public ProxyCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ProxyCreationException(String message) { + super(message); + } + + public ProxyCreationException(Throwable cause) { + super(cause); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java new file mode 100644 index 0000000000..d75ff309ff --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.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.sca.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceReference; + +/** + * Creates proxies that implement Java interfaces and invocation handlers for fronting wires + * + * @version $Rev$ $Date$ + */ + +public interface ProxyFactory { + + /** + * Creates a Java proxy for the given wire + * + * @param interfaze the interface the proxy implements + * @param wire the wire to proxy + * @return the proxy + * @throws ProxyCreationException + */ + T createProxy(Class interfaze, RuntimeWire wire) throws ProxyCreationException; + + /** + * Creates a Java proxy for the given CallableReference + * + * @param callableReference The CallableReference + * @return the proxy + * @throws ProxyCreationException + */ + T createProxy(ServiceReference callableReference) throws ProxyCreationException; + + /** + * Creates a Java proxy for the service contract callback + * + * @param interfaze the interface the proxy should implement + * @return the proxy + * @throws ProxyCreationException + */ + T createCallbackProxy(Class interfaze, List wires) throws ProxyCreationException; + + /** + * Creates a Java proxy for the given callback reference + * + * @param callableReference The CallableReference + * @return the proxy + * @throws ProxyCreationException + */ + T createCallbackProxy(ServiceReferenceImpl callbackReference) throws ProxyCreationException; + + /** + * Cast a proxy to a CallableReference. + * + * @param target a proxy generated by this implementation + * @return a CallableReference (or subclass) equivalent to this proxy + * @throws IllegalArgumentException if the object supplied is not a proxy + */ + > R cast(B target) throws IllegalArgumentException; + + /** + * Test if a given class is a generated proxy class by this factory + * @param clazz A java class or interface + * @return true if the class is a generated proxy class by this factory + */ + boolean isProxyClass(Class clazz); + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java new file mode 100644 index 0000000000..875a252798 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation; + + +/** + * The extension point to plug in proxy factories + * @version $Rev$ $Date$ + */ +public interface ProxyFactoryExtensionPoint { + + /** + * Get the proxy factory for java interfaces + * @return + */ + ProxyFactory getInterfaceProxyFactory(); + + /** + * Get the proxy factory for java classes + * @return + */ + ProxyFactory getClassProxyFactory(); + + /** + * Set the proxy factory for java interfaces + * @param factory + */ + void setInterfaceProxyFactory(ProxyFactory factory); + + /** + * Set the proxy factory for java classes + * @param factory + */ + void setClassProxyFactory(ProxyFactory factory); + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java new file mode 100644 index 0000000000..43726b85dd --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class RuntimeWireInvoker implements Invoker{ + protected MessageFactory messageFactory; + protected Object conversationID; + protected Object callbackID; + protected Object callbackObject; + protected RuntimeWire wire; + + public RuntimeWireInvoker(MessageFactory messageFactory, RuntimeWire wire) { + this.messageFactory = messageFactory; + this.wire = wire; + //init(wire); + } + + /* TODO - EPR - not required for OASIS + protected void init(RuntimeWire wire) { + if (wire != null) { + + ReferenceParameters parameters = wire.getSource().getReferenceParameters(); + this.callbackID = parameters.getCallbackID(); + this.callbackObject = parameters.getCallbackReference(); + this.conversationID = parameters.getConversationID(); + InterfaceContract contract = wire.getSource().getInterfaceContract(); + this.conversational = contract.getInterface().isConversational(); + } + } + */ + + /* + * TODO - Introduced to allow the RuntimeWireInvoker to sit on the end of the + * service binding chain. Runtime wire invoke needs splitting up into + * separate conversation, callback interceptors etc. + */ + public Message invoke(Message msg) { + + try { + Object response = invoke(msg.getOperation(),msg); + // Hack to put the response back in a message. + // shouldn't take it out of the response message in the first place + msg.setBody(response); + } catch (InvocationTargetException e) { +// throw new ServiceRuntimeException(e); + } + + return msg; + } + + public Object invoke(Operation operation, Message msg) throws InvocationTargetException { + return invoke(wire, operation, msg); + } + + public Object invoke(RuntimeWire wire, Operation operation, Message msg) throws InvocationTargetException { + RuntimeWire runtimeWire = wire == null ? this.wire : wire; + InvocationChain chain = runtimeWire.getInvocationChain(operation); + return invoke(chain, msg, runtimeWire); + } + + protected Object invoke(InvocationChain chain, Message msg, RuntimeWire wire) throws InvocationTargetException { + EndpointReference from = msg.getFrom(); + EndpointReference epFrom = wire.getEndpointReference(); + if (from != null) { + from.setComponent(epFrom.getComponent()); + from.setReference(epFrom.getReference()); + from.setBinding(epFrom.getBinding()); + from.setInterfaceContract(epFrom.getInterfaceContract()); + from.setTargetEndpoint(epFrom.getTargetEndpoint()); + //from.setCallbackEndpoint(epFrom.getCallbackEndpoint()); + + // TODO - EPR - what's going on here? + //from.mergeEndpoint(epFrom); + } else { + msg.setFrom(epFrom); + } + msg.setTo(wire.getEndpoint()); + + Invoker headInvoker = chain.getHeadInvoker(); + Operation operation = chain.getTargetOperation(); + msg.setOperation(operation); + + Message msgContext = ThreadMessageContext.getMessageContext(); + // TODO - EPR - no required for OASIS + //Object currentConversationID = msgContext.getFrom().getReferenceParameters().getConversationID(); + + ThreadMessageContext.setMessageContext(msg); + try { + // TODO - EPR - no required for OASIS + //conversationPreinvoke(msg); + // handleCallback(msg, currentConversationID); + // dispatch the wire down the chain and get the response + Message resp = headInvoker.invoke(msg); + Object body = resp.getBody(); + if (resp.isFault()) { + throw new InvocationTargetException((Throwable)body); + } + return body; + } catch (InvocationTargetException e) { + throw e; + } catch (Throwable e) { + throw new ServiceRuntimeException(e); + } finally { + try { + // TODO - EPR - no required for OASIS + //conversationPostInvoke(msg); + //} catch (TargetDestructionException e) { + // throw new ServiceRuntimeException(e); + } finally { + ThreadMessageContext.setMessageContext(msgContext); + } + } + } + + /** + * @param msgContext + */ + /* TODO - EPR - no required for OASIS + protected EndpointReference getCallbackEndpoint(Message msgContext) { + EndpointReference from = msgContext.getFrom(); + return from == null ? null : from.getReferenceParameters().getCallbackReference(); + } + */ + + /** + * Pre-invoke for the conversation handling + * @param msg + * @throws TargetResolutionException + */ + /* TODO - EPR - no required for OASIS + private void conversationPreinvoke(Message msg) { + if (conversational) { + ReferenceParameters parameters = msg.getFrom().getReferenceParameters(); + // in some cases the ConversationID that should be used comes in with the + // message, e.g. when ws binding is in use. + Object convID = parameters.getConversationID(); + if (convID != null) { + conversationID = convID; + } + conversation = conversationManager.getConversation(conversationID); + + if (conversation == null || conversation.getState() == ConversationState.ENDED) { + conversation = conversationManager.startConversation(conversationID); + conversation.initializeConversationAttributes(wire.getTarget().getComponent()); + } else if (conversation.conversationalAttributesInitialized() == false) { + conversation.initializeConversationAttributes(wire.getTarget().getComponent()); + } else if (conversation.isExpired()){ + throw new ConversationEndedException("Conversation has expired."); + } + + conversation.updateLastReferencedTime(); + + parameters.setConversationID(conversation.getConversationID()); + } + } + */ + + /** + * Post-invoke for the conversation handling + * @param wire + * @param operation + * @throws TargetDestructionException + */ + /* TODO - EPR - no required for OASIS + @SuppressWarnings("unchecked") + private void conversationPostInvoke(Message msg) throws TargetDestructionException { + if (conversational) { + Operation operation = msg.getOperation(); + ConversationSequence sequence = operation.getConversationSequence(); + if (sequence == ConversationSequence.CONVERSATION_END) { + // in some cases the ConversationID that should be used comes in with the + // message, e.g. when ws binding is in use. + Object convID = msg.getFrom().getReferenceParameters().getConversationID(); + if (convID != null) { + conversationID = convID; + } + conversation = conversationManager.getConversation(conversationID); + + // remove conversation id from scope container + ScopeContainer scopeContainer = getConversationalScopeContainer(msg); + + if (scopeContainer != null) { + scopeContainer.remove(conversation.getConversationID()); + } + + conversation.end(); + } + } + } + + @SuppressWarnings("unchecked") + private ScopeContainer getConversationalScopeContainer(Message msg) { + ScopeContainer scopeContainer = null; + + RuntimeComponent component = (RuntimeComponent) msg.getTo().getComponent(); + + if (component instanceof ScopedRuntimeComponent) { + ScopedRuntimeComponent scopedRuntimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer container = scopedRuntimeComponent.getScopeContainer(); + + if ((container != null) && (container.getScope() == Scope.CONVERSATION)) { + scopeContainer = container; + } + } + + return scopeContainer; + } + */ + + + /** + * Minimal wrapper for a callback object contained in a ServiceReference + */ + private static class CallbackObjectWrapper implements InstanceWrapper { + + private T instance; + + private CallbackObjectWrapper(T instance) { + this.instance = instance; + } + + public T getInstance() { + return instance; + } + + public void start() { + // do nothing + } + + public void stop() { + // do nothing + } + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java new file mode 100644 index 0000000000..2fc3d6c7eb --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.impl.NoMethodForOperationException; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +/** + * Uses a wire to return an object instance + * + * @version $Rev$ $Date$ + */ +public class WireObjectFactory implements ObjectFactory { + private Class interfaze; + private RuntimeWire wire; + private ProxyFactory proxyService; + + /** + * Constructor. + * + * @param interfaze the interface to inject on the client + * @param wire the backing wire + * @param proxyService the wire service to create the proxy + * @throws NoMethodForOperationException + */ + public WireObjectFactory(Class interfaze, RuntimeWire wire, ProxyFactory proxyService) { + this.interfaze = interfaze; + this.wire = wire; + this.proxyService = proxyService; + } + + public T getInstance() throws ObjectCreationException { + return new ServiceReferenceImpl(interfaze, wire, proxyService).getProxy(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java new file mode 100644 index 0000000000..aeccfa8b05 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.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.sca.core.invocation.impl; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.concurrent.Future; + +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Response; + +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.oasisopen.sca.ServiceReference; + +public class AsyncJDKInvocationHandler extends JDKInvocationHandler { + private static final long serialVersionUID = 1L; + + public AsyncJDKInvocationHandler(MessageFactory messageFactory, ServiceReference callableReference) { + super(messageFactory, callableReference); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (isAsyncCallback(method)) { + return doInvokeAsyncCallback(proxy, method, args); + } else if (isAsyncPoll(method)) { + return doInvokeAsyncPoll(proxy, method, args); + } else { + return super.invoke(proxy, method, args); + } + } + + protected boolean isAsyncCallback(Method method) { + if (method.getName().endsWith("Async") && (method.getReturnType().isAssignableFrom(Future.class))) { + if (method.getParameterTypes().length > 0) { + return method.getParameterTypes()[method.getParameterTypes().length-1].isAssignableFrom(AsyncHandler.class); + } + } + return false; + } + + protected boolean isAsyncPoll(Method method) { + return method.getName().endsWith("Async") && (method.getReturnType().isAssignableFrom(Response.class)); + } + + protected AsyncResponse doInvokeAsyncPoll(Object proxy, Method asyncMethod, Object[] args) { + Object response; + boolean isException; + try { + response = super.invoke(proxy, getNonAsyncMethod(asyncMethod), args); + isException = false; + } catch (Throwable e) { + response = e; + isException = true; + } + return new AsyncResponse(response, isException); + } + + private Object doInvokeAsyncCallback(Object proxy, Method asyncMethod, Object[] args) { + AsyncHandler handler = (AsyncHandler)args[args.length-1]; + Response response = doInvokeAsyncPoll(proxy,asyncMethod,Arrays.copyOf(args, args.length-1)); + handler.handleResponse(response); + + return null; + } + + protected Method getNonAsyncMethod(Method asyncMethod) { + String methodName = asyncMethod.getName().substring(0, asyncMethod.getName().length()-5); + for (Method m : businessInterface.getMethods()) { + if (methodName.equals(m.getName())) { + return m; + } + } + throw new IllegalStateException("No non-async method matching async method " + asyncMethod.getName()); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java new file mode 100644 index 0000000000..07086dfae3 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.xml.ws.Response; + +public class AsyncResponse implements Response { + + private Object response; + private boolean isException; + + public AsyncResponse(Object response, boolean isException) { + this.response = response; + this.isException = isException; + } + + public Map getContext() { + return new HashMap(); + } + + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + public Object get() throws InterruptedException, ExecutionException { + if (isException) { + throw new ExecutionException((Throwable)response); + } else { + return response; + } + } + + public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return get(); + } + + public boolean isCancelled() { + return false; + } + + public boolean isDone() { + return true; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java new file mode 100644 index 0000000000..60914f799b --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.invocation.PhasedInterceptor; + +/** + * Default implementation of an invocation chain + * + * @version $Rev$ $Date$ + */ +public class InvocationChainImpl implements InvocationChain { + private Operation sourceOperation; + private Operation targetOperation; + private List nodes = new ArrayList(); + + private final PhaseManager phaseManager; + private boolean forReference; + private boolean allowsPassByReference; + + public InvocationChainImpl(Operation sourceOperation, Operation targetOperation, boolean forReference, PhaseManager phaseManager) { + this.targetOperation = targetOperation; + this.sourceOperation = sourceOperation; + this.forReference = forReference; + this.phaseManager = phaseManager; + } + + public Operation getTargetOperation() { + return targetOperation; + } + + public void setTargetOperation(Operation operation) { + this.targetOperation = operation; + } + + public void addInterceptor(Interceptor interceptor) { + if (interceptor instanceof PhasedInterceptor) { + PhasedInterceptor pi = (PhasedInterceptor)interceptor; + if (pi.getPhase() != null) { + addInvoker(pi.getPhase(), pi); + return; + } + } + String phase = forReference ? Phase.REFERENCE : Phase.SERVICE; + addInterceptor(phase, interceptor); + } + + public void addInvoker(Invoker invoker) { + if (invoker instanceof PhasedInterceptor) { + PhasedInterceptor pi = (PhasedInterceptor)invoker; + if (pi.getPhase() != null) { + addInvoker(pi.getPhase(), pi); + return; + } + } + String phase = forReference ? Phase.REFERENCE_BINDING : Phase.IMPLEMENTATION; + addInvoker(phase, invoker); + } + + public Invoker getHeadInvoker() { + return nodes.isEmpty() ? null : nodes.get(0).getInvoker(); + } + + /** + * @return the sourceOperation + */ + public Operation getSourceOperation() { + return sourceOperation; + } + + /** + * @param sourceOperation the sourceOperation to set + */ + public void setSourceOperation(Operation sourceOperation) { + this.sourceOperation = sourceOperation; + } + + public void addInterceptor(String phase, Interceptor interceptor) { + addInvoker(phase, interceptor); + } + + private void addInvoker(String phase, Invoker invoker) { + int index = phaseManager.getAllPhases().indexOf(phase); + if (index == -1) { + throw new IllegalArgumentException("Invalid phase name: " + phase); + } + Node node = new Node(index, invoker); + ListIterator li = nodes.listIterator(); + Node before = null, after = null; + boolean found = false; + while (li.hasNext()) { + before = after; + after = li.next(); + if (after.getPhaseIndex() > index) { + // Move back + li.previous(); + li.add(node); + found = true; + break; + } + } + if (!found) { + // Add to the end + nodes.add(node); + before = after; + after = null; + } + + // Relink the interceptors + if (before != null) { + if (before.getInvoker() instanceof Interceptor) { + ((Interceptor)before.getInvoker()).setNext(invoker); + } + } + if (after != null) { + if (invoker instanceof Interceptor) { + ((Interceptor)invoker).setNext(after.getInvoker()); + } + } + + } + + public boolean allowsPassByReference() { + if (allowsPassByReference) { + // No need to check the invokers + return true; + } + // Check if any of the invokers allows pass-by-reference + boolean allowsPBR = false; + for (Node i : nodes) { + if (i.getInvoker() instanceof DataExchangeSemantics) { + if (((DataExchangeSemantics)i.getInvoker()).allowsPassByReference()) { + allowsPBR = true; + break; + } + } + } + return allowsPBR; + } + + public void setAllowsPassByReference(boolean allowsPBR) { + this.allowsPassByReference = allowsPBR; + } + + private static class Node { + private int phaseIndex; + private Invoker invoker; + + public Node(int phaseIndex, Invoker invoker) { + super(); + this.phaseIndex = phaseIndex; + this.invoker = invoker; + } + + public int getPhaseIndex() { + return phaseIndex; + } + + public Invoker getInvoker() { + return invoker; + } + + @Override + public String toString() { + return "(" + phaseIndex + ")" + invoker; + } + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java new file mode 100644 index 0000000000..e64b9f3068 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.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.sca.core.invocation.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + +import org.apache.tuscany.sca.core.assembly.impl.RuntimeWireImpl; +import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl; +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Responsible for dispatching to a callback through a wire.

TODO cache + * target invoker + * + * @version $Rev$ $Date$ + */ +public class JDKCallbackInvocationHandler extends JDKInvocationHandler { + private static final long serialVersionUID = -3350283555825935609L; + + public JDKCallbackInvocationHandler(MessageFactory messageFactory, ServiceReferenceImpl ref) { + super(messageFactory, ref); + this.fixedWire = false; + } + + @Override + @SuppressWarnings( {"unchecked"}) + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + if (Object.class == method.getDeclaringClass()) { + return invokeObjectMethod(method, args); + } + + // obtain a dedicated wire to be used for this callback invocation + RuntimeWire wire = ((CallbackServiceReferenceImpl)callableReference).getCallbackWire(); + if (wire == null) { + //FIXME: need better exception + throw new ServiceRuntimeException("No callback wire found"); + } + + setEndpoint(((CallbackServiceReferenceImpl)callableReference).getResolvedEndpoint()); + + InvocationChain chain = getInvocationChain(method, wire); + if (chain == null) { + throw new IllegalArgumentException("No matching operation is found: " + method); + } + + try { + return invoke(chain, args, wire, wire.getEndpointReference()); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + throw e; + } finally { + // allow the cloned wire to be reused by subsequent callbacks + ((RuntimeWireImpl)wire).releaseWire(); + } + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java new file mode 100644 index 0000000000..148749922e --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java @@ -0,0 +1,537 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation.impl; + +import java.io.Serializable; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.core.context.ServiceReferenceExt; +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.SCARuntimeException; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class JDKInvocationHandler implements InvocationHandler, Serializable { + private static final long serialVersionUID = -3366410500152201371L; + + protected boolean conversational; + protected MessageFactory messageFactory; + protected EndpointReference source; + protected Endpoint target; + protected RuntimeWire wire; + protected ServiceReferenceExt callableReference; + protected Class businessInterface; + + protected boolean fixedWire = true; + + protected transient Map chains = new HashMap(); + + public JDKInvocationHandler(MessageFactory messageFactory, Class businessInterface, RuntimeWire wire) { + this.messageFactory = messageFactory; + this.wire = wire; + this.businessInterface = businessInterface; + init(this.wire); + } + + public JDKInvocationHandler(MessageFactory messageFactory, ServiceReference callableReference) { + this.messageFactory = messageFactory; + this.callableReference = (ServiceReferenceExt)callableReference; + if (callableReference != null) { + this.businessInterface = callableReference.getBusinessInterface(); + this.wire = ((ServiceReferenceExt)callableReference).getRuntimeWire(); + if (wire != null) { + init(wire); + } + } + } + + protected void init(RuntimeWire wire) { + // TODO - EPR not required for OASIS + /* + if (wire != null) { + try { + // Clone the endpoint reference so that reference parameters can be changed + source = (EndpointReference)wire.getSource().clone(); + } catch (CloneNotSupportedException e) { + throw new ServiceRuntimeException(e); + } + initConversational(wire); + } + */ + } + + /* TODO - EPR - not required for OASIS + protected void initConversational(RuntimeWire wire) { + InterfaceContract contract = wire.getSource().getInterfaceContract(); + this.conversational = contract.getInterface().isConversational(); + } + */ + + public Class getBusinessInterface() { + return businessInterface; + } + + + protected Object getCallbackID() { +// if (callableReference != null) { +// return callableReference.getCallbackID(); +// } else { + return null; +// } + } + + /* TODO - EPR - Not reqiured for OASIS + protected Object getCallbackObject() { + if (callableReference != null && callableReference instanceof ServiceReference) { + return ((ServiceReference)callableReference).getService(); + } else { + return null; + } + } + */ + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (Object.class == method.getDeclaringClass()) { + return invokeObjectMethod(method, args); + } + if (wire == null) { + throw new ServiceRuntimeException("No runtime wire is available"); + } + + if (wire.isOutOfDate()) { + wire.rebuild(); + chains.clear(); + } + + InvocationChain chain = getInvocationChain(method, wire); + + if (chain == null) { + throw new IllegalArgumentException("No matching operation is found: " + method); + } + + // The EndpointReference is not now resolved until the invocation chain + // is first created so reset the source here + source = wire.getEndpointReference(); + + // send the invocation down the wire + Object result = invoke(chain, args, wire, source); + + return result; + } + + /** + * Handle the methods on the Object.class + * @param method + * @param args + */ + protected Object invokeObjectMethod(Method method, Object[] args) throws Throwable { + String name = method.getName(); + if ("toString".equals(name)) { + return "[Proxy - " + toString() + "]"; + } else if ("equals".equals(name)) { + Object obj = args[0]; + if (obj == null) { + return false; + } + if (!Proxy.isProxyClass(obj.getClass())) { + return false; + } + return equals(Proxy.getInvocationHandler(obj)); + } else if ("hashCode".equals(name)) { + return hashCode(); + } else { + return method.invoke(this); + } + } + + /** + * Determines if the given operation matches the given method + * + * @return true if the operation matches, false if does not + */ + // FIXME: Should it be in the InterfaceContractMapper? + @SuppressWarnings("unchecked") + private static boolean match(Operation operation, Method method) { + if (operation instanceof JavaOperation) { + JavaOperation javaOp = (JavaOperation)operation; + Method m = javaOp.getJavaMethod(); + if (!method.getName().equals(m.getName())) { + return false; + } + if (method.equals(m)) { + return true; + } + } else { + if (!method.getName().equals(operation.getName())) { + return false; + } + } + + // For remotable interface, operation is not overloaded. + if (operation.getInterface().isRemotable()) { + return true; + } + + Class[] params = method.getParameterTypes(); + + DataType> inputType = null; + if (operation.isWrapperStyle()) { + inputType = operation.getWrapper().getUnwrappedInputType(); + } else { + inputType = operation.getInputType(); + } + List types = inputType.getLogical(); + boolean matched = true; + if (types.size() == params.length && method.getName().equals(operation.getName())) { + for (int i = 0; i < params.length; i++) { + Class clazz = params[i]; + Class type = types.get(i).getPhysical(); + // Object.class.isAssignableFrom(int.class) returns false + if (type != Object.class && (!type.isAssignableFrom(clazz))) { + matched = false; + } + } + } else { + matched = false; + } + return matched; + + } + + protected synchronized InvocationChain getInvocationChain(Method method, RuntimeWire wire) { + if (fixedWire && chains.containsKey(method)) { + return chains.get(method); + } + InvocationChain found = null; + for (InvocationChain chain : wire.getInvocationChains()) { + Operation operation = chain.getSourceOperation(); + if (operation.isDynamic()) { + operation.setName(method.getName()); + found = chain; + break; + } else if (match(operation, method)) { + found = chain; + break; + } + } + if (fixedWire) { + chains.put(method, found); + } + return found; + } + + protected void setEndpoint(Endpoint endpoint) { + this.target = endpoint; + } + + protected Object invoke(InvocationChain chain, Object[] args, RuntimeWire wire, EndpointReference source) + throws Throwable { + Message msg = messageFactory.createMessage(); + msg.setFrom(source); + if (target != null) { + msg.setTo(target); + } else { + msg.setTo(wire.getEndpoint()); + } + Invoker headInvoker = chain.getHeadInvoker(); + Operation operation = chain.getTargetOperation(); + msg.setOperation(operation); + msg.setBody(args); + + Message msgContext = ThreadMessageContext.getMessageContext(); + + // TODO - EPR - not required for OASIS + //Object currentConversationID = msgContext.getFrom().getReferenceParameters().getConversationID(); + //conversationPreinvoke(msg, wire); + + handleCallback(msg, wire); + ThreadMessageContext.setMessageContext(msg); + boolean abnormalEndConversation = false; + try { + // dispatch the wire down the chain and get the response + Message resp = headInvoker.invoke(msg); + Object body = resp.getBody(); + if (resp.isFault()) { + /* TODO - EPR - not required in OASIS + // mark the conversation as ended if the exception is not a business exception + if (currentConversationID != null ){ + try { + boolean businessException = false; + + for (DataType dataType : operation.getFaultTypes()){ + if (dataType.getPhysical() == ((Throwable)body).getClass()){ + businessException = true; + break; + } + } + + if (businessException == false){ + abnormalEndConversation = true; + } + } catch (Exception ex){ + // TODO - sure what the best course of action is here. We have + // a system exception in the middle of a business exception + } + } + */ + throw (Throwable)body; + } + return body; + } finally { + //conversationPostInvoke(msg, wire, abnormalEndConversation); + ThreadMessageContext.setMessageContext(msgContext); + } + } + + /** + * @param msg + * @param wire + * @param interfaze + * @throws TargetResolutionException + */ + private void handleCallback(Message msg, RuntimeWire wire) + throws TargetResolutionException { + + //ReferenceParameters parameters = msg.getFrom().getReferenceParameters(); + //parameters.setCallbackID(getCallbackID()); + + if (msg.getFrom() == null || msg.getFrom().getCallbackEndpoint() == null) { + return; + } + + /* TODO - EPR - not required for OASIS + parameters.setCallbackReference(msg.getFrom().getCallbackEndpoint()); + + // If we are passing out a callback target + // register the calling component instance against this + // new conversation id so that stateful callbacks will be + // able to find it + Object callbackObject = getCallbackObject(); + if (conversational && callbackObject == null) { + // the component instance is already registered + // so add another registration + ScopeContainer scopeContainer = getConversationalScopeContainer(wire); + + if (scopeContainer != null && currentConversationID != null) { + scopeContainer.addWrapperReference(currentConversationID, conversation.getConversationID()); + } + } + + Interface interfaze = msg.getFrom().getCallbackEndpoint().getInterfaceContract().getInterface(); + if (callbackObject != null) { + if (callbackObject instanceof ServiceReference) { + CallableReferenceExt callableReference = (CallableReferenceExt)callbackObject; + EndpointReference callbackRef = callableReference.getEndpointReference(); + + // TODO - EPR - create chains on the callback reference in case this hasn't already happened + // needed as the bindings are not now matched until the chanins are created + callableReference.getRuntimeWire().getInvocationChains(); + + parameters.setCallbackReference(callbackRef); + } else { + if (interfaze != null) { + if (!interfaze.isConversational()) { + throw new IllegalArgumentException( + "Callback object for stateless callback is not a ServiceReference"); + } else { + if (!(callbackObject instanceof Serializable)) { + throw new IllegalArgumentException( + "Callback object for stateful callback is not Serializable"); + } + ScopeContainer scopeContainer = getConversationalScopeContainer(wire); + if (scopeContainer != null) { + InstanceWrapper wrapper = new CallbackObjectWrapper(callbackObject); + scopeContainer.registerWrapper(wrapper, conversation.getConversationID()); + } + parameters.setCallbackObjectID(callbackObject); + } + } + } + } + */ + } + + /** + * Pre-invoke for the conversation handling + * @param msg + * @throws TargetResolutionException + */ + /* TODO - EPR - not required for OASIS + private void conversationPreinvoke(Message msg, RuntimeWire wire) { + if (!conversational) { + // Not conversational or the conversation has been started + return; + } + + ConversationManager conversationManager = ((RuntimeWireImpl2)wire).getConversationManager(); + + if (conversation == null || conversation.getState() == ConversationState.ENDED) { + + conversation = conversationManager.startConversation(getConversationID()); + + // if this is a local wire then set up the conversation timeouts here based on the + // parameters from the component + if (wire.getEndpoint().getComponent() != null){ + conversation.initializeConversationAttributes((RuntimeComponent)wire.getEndpoint().getComponent()); + } + + // connect the conversation to the CallableReference so it can be retrieve in the future + if (callableReference != null) { + ((CallableReferenceImpl)callableReference).attachConversation(conversation); + } + } else if (conversation.isExpired()) { + throw new ConversationEndedException("Conversation " + conversation.getConversationID() + " has expired."); + } + + // if this is a local wire then schedule conversation timeouts based on the timeout + // parameters from the service implementation. If this isn't a local wire then + // the RuntimeWireInvoker will take care of this + if (wire.getEndpoint().getComponent() != null){ + conversation.updateLastReferencedTime(); + } + + msg.getFrom().getReferenceParameters().setConversationID(conversation.getConversationID()); + + } + */ + + /** + * Post-invoke for the conversation handling + * @param wire + * @param operation + * @throws TargetDestructionException + */ + /* TODO - not required for OASIS + @SuppressWarnings("unchecked") + private void conversationPostInvoke(Message msg, RuntimeWire wire, boolean abnormalEndConversation) + throws TargetDestructionException { + Operation operation = msg.getOperation(); + ConversationSequence sequence = operation.getConversationSequence(); + // We check that conversation has not already ended as there is only one + // conversation manager in the runtime and so, in the case of remote bindings, + // the conversation will already have been stopped when we get back to the client + if ((sequence == ConversationSequence.CONVERSATION_END || abnormalEndConversation) && + (conversation.getState() != ConversationState.ENDED)) { + + // remove conversation id from scope container + ScopeContainer scopeContainer = getConversationalScopeContainer(wire); + + if (scopeContainer != null) { + scopeContainer.remove(conversation.getConversationID()); + } + + conversation.end(); + } + } + + + private ScopeContainer getConversationalScopeContainer(RuntimeWire wire) { + ScopeContainer scopeContainer = null; + + RuntimeComponent runtimeComponent = (RuntimeComponent)wire.getEndpointReference().getComponent(); + + if (runtimeComponent instanceof ScopedRuntimeComponent) { + ScopedRuntimeComponent scopedRuntimeComponent = (ScopedRuntimeComponent)runtimeComponent; + ScopeContainer tmpScopeContainer = scopedRuntimeComponent.getScopeContainer(); + + if ((tmpScopeContainer != null) && (tmpScopeContainer.getScope() == Scope.CONVERSATION)) { + scopeContainer = tmpScopeContainer; + } + } + + return scopeContainer; + } + */ + + /** + * Creates a new conversation id + * + * @return the conversation id + */ + /* TODO - EPR - not required for OASIS + private Object createConversationID() { + if (getConversationID() != null) { + return getConversationID(); + } else { + return UUID.randomUUID().toString(); + } + } + */ + + /** + * @return the callableReference + */ + public ServiceReference getCallableReference() { + return callableReference; + } + + /** + * @param callableReference the callableReference to set + */ + public void setCallableReference(ServiceReference callableReference) { + this.callableReference = (ServiceReferenceExt)callableReference; + } + + /** + * Minimal wrapper for a callback object contained in a ServiceReference + */ + private static class CallbackObjectWrapper implements InstanceWrapper { + + private T instance; + + private CallbackObjectWrapper(T instance) { + this.instance = instance; + } + + public T getInstance() { + return instance; + } + + public void start() { + // do nothing + } + + public void stop() { + // do nothing + } + + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java new file mode 100644 index 0000000000..853e28fafa --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.concurrent.Future; + +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Response; + +import org.apache.tuscany.sca.common.java.collection.LRUCache; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl; +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.invocation.ProxyCreationException; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.oasisopen.sca.ServiceReference; + + +/** + * the default implementation of a wire service that uses JDK dynamic proxies + * + * @version $Rev$ $Date$ + */ +public class JDKProxyFactory implements ProxyFactory, LifeCycleListener { + protected InterfaceContractMapper contractMapper; + private MessageFactory messageFactory; + + public JDKProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.contractMapper = mapper; + this.messageFactory = messageFactory; + } + + /** + * The original createProxy method assumes that the proxy doesn't want to + * share conversation state so sets the conversation object to null + */ + public T createProxy(Class interfaze, RuntimeWire wire) throws ProxyCreationException { + ServiceReference serviceReference = new ServiceReferenceImpl(interfaze, wire, this); + return createProxy(serviceReference); + } + + public T createProxy(ServiceReference callableReference) throws ProxyCreationException { + assert callableReference != null; + final Class interfaze = callableReference.getBusinessInterface(); + InvocationHandler handler; + if (isAsync(interfaze)) { + handler = new AsyncJDKInvocationHandler(messageFactory, callableReference); + } else { + handler = new JDKInvocationHandler(messageFactory, callableReference); + } + // Allow privileged access to class loader. Requires RuntimePermission in security policy. + ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction() { + public ClassLoader run() { + return interfaze.getClassLoader(); + } + }); + Object proxy = newProxyInstance(cl, new Class[] {interfaze}, handler); + ((ServiceReferenceImpl)callableReference).setProxy(proxy); + return interfaze.cast(proxy); + } + + private boolean isAsync(Class interfaze) { + for (Method method : interfaze.getMethods()) { + if (method.getName().endsWith("Async")) { + if (method.getReturnType().isAssignableFrom(Future.class)) { + if (method.getParameterTypes().length > 0) { + if (method.getParameterTypes()[method.getParameterTypes().length-1].isAssignableFrom(AsyncHandler.class)) { + return true; + } + } + } + if (method.getReturnType().isAssignableFrom(Response.class)) { + return true; + } + } + } + return false; + } + + public T createCallbackProxy(Class interfaze, List wires) throws ProxyCreationException { + ServiceReferenceImpl callbackReference = new CallbackServiceReferenceImpl(interfaze, wires, this); + return callbackReference != null ? createCallbackProxy(callbackReference) : null; + } + + public T createCallbackProxy(ServiceReferenceImpl callbackReference) throws ProxyCreationException { + assert callbackReference != null; + Class interfaze = callbackReference.getBusinessInterface(); + InvocationHandler handler = new JDKCallbackInvocationHandler(messageFactory, callbackReference); + ClassLoader cl = interfaze.getClassLoader(); + Object proxy = newProxyInstance(cl, new Class[] {interfaze}, handler); + callbackReference.setProxy(proxy); + return interfaze.cast(proxy); + } + + public > R cast(B target) throws IllegalArgumentException { + InvocationHandler handler = Proxy.getInvocationHandler(target); + if (handler instanceof JDKInvocationHandler) { + return (R)((JDKInvocationHandler)handler).getCallableReference(); + } else { + throw new IllegalArgumentException("The object is not a known proxy."); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class) + */ + public boolean isProxyClass(Class clazz) { + return Proxy.isProxyClass(clazz); + } + + // This is a cache containing the proxy class constructor for each business interface. + // This improves performance compared to calling Proxy.newProxyInstance() + // every time that a proxy is needed. + private final LRUCache, Constructor> cache = new LRUCache, Constructor>(512); + + public Object newProxyInstance(ClassLoader classloader, + Class interfaces[], + InvocationHandler invocationhandler) throws IllegalArgumentException { + if (interfaces.length > 1) { + // We only cache the proxy constructors with one single interface which the case in SCA where + // one reference can have one interface + return Proxy.newProxyInstance(classloader, interfaces, invocationhandler); + } + try { + if (invocationhandler == null) + throw new NullPointerException("InvocationHandler is null"); + // Lookup cached constructor. aclass[0] is the reference's business interface. + Constructor proxyCTOR; + synchronized (cache) { + proxyCTOR = cache.get(interfaces[0]); + } + if (proxyCTOR == null) { + Class proxyClass = Proxy.getProxyClass(classloader, interfaces); + proxyCTOR = proxyClass.getConstructor(InvocationHandler.class); + synchronized (cache) { + cache.put(interfaces[0], proxyCTOR); + } + } + return proxyCTOR.newInstance(invocationhandler); + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + public void start() { + } + + public void stop() { + cache.clear(); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java new file mode 100644 index 0000000000..6ce2ffca21 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.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.sca.core.invocation.impl; + +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; + +/** + * Implementation of MessageFactory. + * + * @version $Rev$ $Date$ + */ +public class MessageFactoryImpl implements MessageFactory { + + public Message createMessage() { + return new MessageImpl(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java new file mode 100644 index 0000000000..53fab3392c --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Message; + +/** + * The default implementation of a message flowed through a wire during an invocation + * + * @version $Rev $Date$ + */ +public class MessageImpl implements Message { + private List headers = new ArrayList(); + private Object body; + private Object messageID; + private boolean isFault; + private Operation operation; + + private EndpointReference from; + private Endpoint to; + + private Object bindingContext; + + public MessageImpl() { + // TODO - EPR - What to do by default? + //this.from = new EndpointReferenceImpl("/"); + //this.to = new EndpointReferenceImpl("/"); + this.from = null; + this.to = null; + } + + @SuppressWarnings("unchecked") + public T getBody() { + return (T)body; + } + + public void setBody(T body) { + this.isFault = false; + this.body = body; + } + + public Object getMessageID() { + return messageID; + } + + public void setMessageID(Object messageId) { + this.messageID = messageId; + } + + public boolean isFault() { + return isFault; + } + + public void setFaultBody(Object fault) { + this.isFault = true; + this.body = fault; + } + + public EndpointReference getFrom() { + return from; + } + + public void setFrom(EndpointReference from) { + this.from = from; + } + + public Endpoint getTo() { + return to; + } + + public void setTo(Endpoint to) { + this.to = to; + } + + public Operation getOperation() { + return operation; + } + + public void setOperation(Operation op) { + this.operation = op; + } + + public List getHeaders() { + return headers; + } + + @SuppressWarnings("unchecked") + public T getBindingContext() { + return (T)bindingContext; + } + + public void setBindingContext(T bindingContext) { + this.bindingContext = bindingContext; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java new file mode 100644 index 0000000000..45f4bf52bf --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.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.sca.core.invocation.impl; + +import org.apache.tuscany.sca.core.invocation.ProxyCreationException; + + +/** + * Thrown when an {@link org.apache.tuscany.sca.core.factory.model.Operation} cannot be mapped to a method on an interface + * @version $Rev$ $Date$ + */ +public class NoMethodForOperationException extends ProxyCreationException { + private static final long serialVersionUID = 5116536602309483679L; + + 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/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java new file mode 100644 index 0000000000..1649eade87 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java @@ -0,0 +1,313 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation.impl; + +import static org.apache.tuscany.sca.invocation.Phase.IMPLEMENTATION; +import static org.apache.tuscany.sca.invocation.Phase.IMPLEMENTATION_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_TRANSPORT; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_WIREFORMAT; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_INTERFACE; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_OPERATION_SELECTOR; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_TRANSPORT; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_WIREFORMAT; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_INTERFACE; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_POLICY; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.invocation.Phase; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class PhaseManager { + private static final Logger log = Logger.getLogger(PhaseManager.class.getName()); + + public static final String STAGE_REFERENCE = "reference"; + public static final String STAGE_REFERENCE_BINDING = "reference.binding"; + public static final String STAGE_SERVICE_BINDING = "service.binding"; + public static final String STAGE_SERVICE = "service"; + public static final String STAGE_IMPLEMENTATION = "implementation"; + + private static final String[] SYSTEM_REFERENCE_PHASES = + {REFERENCE, REFERENCE_INTERFACE, REFERENCE_POLICY, REFERENCE_BINDING}; + + private static final String[] SYSTEM_REFERENCE_BINDING_PHASES = + {REFERENCE_BINDING_WIREFORMAT, REFERENCE_BINDING_POLICY, REFERENCE_BINDING_TRANSPORT}; + + private static final String[] SYSTEM_SERVICE_BINDING_PHASES = + {SERVICE_BINDING_TRANSPORT, SERVICE_BINDING_OPERATION_SELECTOR, SERVICE_BINDING_WIREFORMAT, SERVICE_BINDING_POLICY}; + + private static final String[] SYSTEM_SERVICE_PHASES = + {SERVICE_BINDING, SERVICE_POLICY, SERVICE_INTERFACE, SERVICE}; + + private static final String[] SYSTEM_IMPLEMENTATION_PHASES = {IMPLEMENTATION_POLICY, IMPLEMENTATION}; + + private ExtensionPointRegistry registry; + private String pattern = Phase.class.getName(); + private Map stages; + private List phases; + + public class Stage { + private String name; + private PhaseSorter sorter = new PhaseSorter(); + private Set firstSet = new HashSet(); + private Set lastSet = new HashSet(); + private List phases = new ArrayList(); + + public Stage(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + public PhaseSorter getSorter() { + return sorter; + } + + public Set getFirstSet() { + return firstSet; + } + + public Set getLastSet() { + return lastSet; + } + + public List getPhases() { + return phases; + } + + @Override + public String toString() { + return name + phases; + } + } + + /** + * @param registry + */ + public PhaseManager(ExtensionPointRegistry registry) { + super(); + this.registry = registry; + } + + public static PhaseManager getInstance(ExtensionPointRegistry registry) { + UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class); + return utilityExtensionPoint.getUtility(PhaseManager.class); + } + + // For unit test purpose + PhaseManager(String pattern) { + super(); + this.pattern = pattern; + this.registry = new DefaultExtensionPointRegistry(); + } + + private List getPhases(String stage) { + Stage s = getStages().get(stage); + return s == null ? null : s.getPhases(); + } + + public List getReferencePhases() { + return getPhases(STAGE_REFERENCE); + } + + public List getServicePhases() { + return getPhases(STAGE_SERVICE); + } + + public List getReferenceBindingPhases() { + return getPhases(STAGE_REFERENCE_BINDING); + } + + public List getServiceBindingPhases() { + return getPhases(STAGE_SERVICE_BINDING); + } + + public List getImplementationPhases() { + return getPhases(STAGE_IMPLEMENTATION); + } + + public synchronized List getAllPhases() { + if (phases == null) { + phases = new ArrayList(); + phases.addAll(getReferencePhases()); + phases.addAll(getReferenceBindingPhases()); + phases.addAll(getServiceBindingPhases()); + phases.addAll(getServicePhases()); + phases.addAll(getImplementationPhases()); + } + return phases; + } + + public synchronized Map getStages() { + if (stages != null) { + return stages; + } + init(); + + Collection services; + try { + services = registry.getServiceDiscovery().getServiceDeclarations(pattern); + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } + + for (ServiceDeclaration d : services) { + if (log.isLoggable(Level.FINE)) { + log.fine(d.getLocation() + ": " + d.getAttributes()); + } + String name = d.getAttributes().get("name"); + if (name == null) { + throw new ServiceRuntimeException("Required attribute 'name' is missing."); + } + String stageName = d.getAttributes().get("stage"); + if (stageName == null) { + throw new ServiceRuntimeException("Required attribute 'stage' is missing."); + } + Stage stage = stages.get(stageName); + if (stage == null) { + throw new ServiceRuntimeException("Invalid stage: " + stageName); + } + PhaseSorter graph = stage.getSorter(); + Set firstSet = stage.getFirstSet(), lastSet = stage.getLastSet(); + + String before = d.getAttributes().get("before"); + String after = d.getAttributes().get("after"); + if (before != null) { + StringTokenizer tokenizer = new StringTokenizer(before); + while (tokenizer.hasMoreTokens()) { + String p = tokenizer.nextToken(); + if (!"*".equals(p)) { + graph.addEdge(name, p); + } else { + firstSet.add(name); + } + } + } + if (after != null) { + StringTokenizer tokenizer = new StringTokenizer(after); + while (tokenizer.hasMoreTokens()) { + String p = tokenizer.nextToken(); + if (!"*".equals(p)) { + graph.addEdge(p, name); + } else { + lastSet.add(name); + } + } + } + graph.addVertext(name); + if(firstSet.size()>1) { + log.warning("More than one phases are declared to be first: "+firstSet); + } + for (String s : firstSet) { + for (String v : new HashSet(graph.getVertices().keySet())) { + if (!firstSet.contains(v)) { + graph.addEdge(s, v); + } + } + } + if(lastSet.size()>1) { + log.warning("More than one phases are declared to be the last: "+lastSet); + } + for (String s : lastSet) { + for (String v : new HashSet(graph.getVertices().keySet())) { + if (!lastSet.contains(v)) { + graph.addEdge(v, s); + } + } + } + + } + + for (Stage s : stages.values()) { + List phases = s.getSorter().topologicalSort(false); + s.getPhases().clear(); + s.getPhases().addAll(phases); + } + if (log.isLoggable(Level.FINE)) { + log.fine("Stages: " + stages); + } + return stages; + } + + private void init() { + stages = new HashMap(); + + Stage referenceStage = new Stage(STAGE_REFERENCE); + for (int i = 1; i < SYSTEM_REFERENCE_PHASES.length; i++) { + referenceStage.getSorter().addEdge(SYSTEM_REFERENCE_PHASES[i - 1], SYSTEM_REFERENCE_PHASES[i]); + } + referenceStage.getLastSet().add(REFERENCE_BINDING); + stages.put(referenceStage.getName(), referenceStage); + + Stage referenceBindingStage = new Stage(STAGE_REFERENCE_BINDING); + for (int i = 1; i < SYSTEM_REFERENCE_BINDING_PHASES.length; i++) { + referenceBindingStage.getSorter().addEdge(SYSTEM_REFERENCE_BINDING_PHASES[i - 1], SYSTEM_REFERENCE_BINDING_PHASES[i]); + } + stages.put(referenceBindingStage.getName(), referenceBindingStage); + + Stage serviceBindingStage = new Stage(STAGE_SERVICE_BINDING); + for (int i = 1; i < SYSTEM_SERVICE_BINDING_PHASES.length; i++) { + serviceBindingStage.getSorter().addEdge(SYSTEM_SERVICE_BINDING_PHASES[i - 1], SYSTEM_SERVICE_BINDING_PHASES[i]); + } + stages.put(serviceBindingStage.getName(), serviceBindingStage); + + + Stage serviceStage = new Stage(STAGE_SERVICE); + for (int i = 1; i < SYSTEM_SERVICE_PHASES.length; i++) { + serviceStage.getSorter().addEdge(SYSTEM_SERVICE_PHASES[i - 1], SYSTEM_SERVICE_PHASES[i]); + } + stages.put(serviceStage.getName(), serviceStage); + + Stage implementationStage = new Stage(STAGE_IMPLEMENTATION); + for (int i = 1; i < SYSTEM_IMPLEMENTATION_PHASES.length; i++) { + implementationStage.getSorter().addEdge(SYSTEM_IMPLEMENTATION_PHASES[i - 1], + SYSTEM_IMPLEMENTATION_PHASES[i]); + } + implementationStage.getLastSet().add(IMPLEMENTATION); + stages.put(implementationStage.getName(), implementationStage); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java new file mode 100644 index 0000000000..175f3463ad --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java @@ -0,0 +1,236 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Directed, weighted graph + * + * @param The type of vertex object + * @param The type of edge object + * + * @version $Rev$ $Date$ + */ +public class PhaseSorter implements Cloneable { + private final Map vertices = new HashMap(); + + /** + * 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 outEdges = new HashMap(); + private Map inEdges = new HashMap(); + + private Vertex(V value) { + this.value = value; + } + + @Override + public String toString() { + return "(" + value + ")"; + } + + public V getValue() { + return value; + } + + public Map getOutEdges() { + return outEdges; + } + + public Map getInEdges() { + return inEdges; + } + + } + + /** + * An Edge connects two vertices in one direction + */ + public final class Edge { + private Vertex sourceVertex; + + private Vertex targetVertex; + + public Edge(Vertex source, Vertex target) { + this.sourceVertex = source; + this.targetVertex = target; + } + + @Override + public String toString() { + return sourceVertex + "->" + targetVertex; + } + + public Vertex getTargetVertex() { + return targetVertex; + } + + public void setTargetVertex(Vertex vertex) { + this.targetVertex = vertex; + } + + public Vertex getSourceVertex() { + return sourceVertex; + } + + public void setSourceVertex(Vertex sourceVertex) { + this.sourceVertex = sourceVertex; + } + } + + public void addEdge(V source, V target) { + 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); + s.outEdges.put(t, edge); + t.inEdges.put(s, edge); + } + + public void addVertext(V source) { + Vertex s = getVertex(source); + if (s == null) { + s = new Vertex(source); + vertices.put(source, s); + } + } + + 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 && t.inEdges.remove(s) != null; + + } + + public void removeEdge(Edge edge) { + edge.sourceVertex.outEdges.remove(edge.targetVertex); + edge.targetVertex.inEdges.remove(edge.sourceVertex); + } + + public void removeVertex(Vertex vertex) { + vertices.remove(vertex.getValue()); + for (Edge e : new ArrayList(vertex.outEdges.values())) { + removeEdge(e); + } + for (Edge e : new ArrayList(vertex.inEdges.values())) { + removeEdge(e); + } + } + + public Edge getEdge(Vertex source, Vertex target) { + return source.outEdges.get(target); + } + + public Edge getEdge(V source, V target) { + Vertex sv = getVertex(source); + if (sv == null) { + return null; + } + Vertex tv = getVertex(target); + if (tv == null) { + return null; + } + return getEdge(getVertex(source), getVertex(target)); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Vertex v : vertices.values()) { + sb.append(v.outEdges.values()).append("\n"); + } + return sb.toString(); + } + + public Map getVertices() { + return vertices; + } + + public void addGraph(PhaseSorter otherGraph) { + for (Vertex v : otherGraph.vertices.values()) { + for (Edge e : v.outEdges.values()) { + addEdge(e.sourceVertex.value, e.targetVertex.value); + } + } + } + + private Vertex getFirst() { + for (Vertex v : vertices.values()) { + if (v.inEdges.isEmpty()) { + return v; + } + } + if (!vertices.isEmpty()) { + throw new IllegalArgumentException("Circular ordering has been detected: " + toString()); + } else { + return null; + } + } + + public List topologicalSort(boolean readOnly) { + PhaseSorter graph = (!readOnly) ? this : (PhaseSorter)clone(); + List list = new ArrayList(); + while (true) { + Vertex v = graph.getFirst(); + if (v == null) { + break; + } + list.add(v.getValue()); + graph.removeVertex(v); + } + + return list; + } + + @Override + public Object clone() { + PhaseSorter copy = new PhaseSorter(); + copy.addGraph(this); + return copy; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/DefaultDomainRegistryFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/DefaultDomainRegistryFactory.java new file mode 100644 index 0000000000..3240b4e50d --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/DefaultDomainRegistryFactory.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.sca.core.runtime; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.runtime.DomainRegistryFactory; +import org.apache.tuscany.sca.runtime.EndpointListener; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * The utility responsible for finding the endpoint regstry by the scheme and creating instances for the + * given domain + */ +public class DefaultDomainRegistryFactory implements DomainRegistryFactory, LifeCycleListener { + private ExtensionPointRegistry extensionRegistry; + private Map declarations = new HashMap(); + private Map endpointRegistries = new ConcurrentHashMap(); + private List listeners = new ArrayList(); + + /** + * @param extensionRegistry + */ + public DefaultDomainRegistryFactory(ExtensionPointRegistry extensionRegistry) { + super(); + this.extensionRegistry = extensionRegistry; + } + + public void start() { + Collection sds = null; + try { + sds = extensionRegistry.getServiceDiscovery().getServiceDeclarations(EndpointRegistry.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + for (ServiceDeclaration sd : sds) { + String scheme = sd.getAttributes().get("scheme"); + if (scheme != null) { + scheme = scheme.toLowerCase(); + } + declarations.put(scheme, sd); + } + } + + public synchronized EndpointRegistry getEndpointRegistry(String endpointRegistryURI, String domainURI) { + if (endpointRegistryURI == null) { + endpointRegistryURI = "vm://localhost"; + } + + String key = endpointRegistryURI + "," + domainURI; + + EndpointRegistry endpointRegistry = endpointRegistries.get(key); + if (endpointRegistry != null) { + return endpointRegistry; + } + + URI uri = URI.create(endpointRegistryURI); + String scheme = uri.getScheme(); + if (scheme != null) { + scheme = scheme.toLowerCase(); + } + + ServiceDeclaration sd = declarations.get(scheme); + + try { + Class implClass = sd.loadClass(); + Constructor constructor = null; + try { + constructor = implClass.getConstructor(ExtensionPointRegistry.class, String.class, String.class); + endpointRegistry = + (EndpointRegistry)constructor.newInstance(extensionRegistry, endpointRegistryURI, domainURI); + } catch (NoSuchMethodException e) { + constructor = + implClass.getConstructor(ExtensionPointRegistry.class, Map.class, String.class, String.class); + endpointRegistry = + (EndpointRegistry)constructor.newInstance(extensionRegistry, + sd.getAttributes(), + endpointRegistryURI, + domainURI); + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + + if (endpointRegistry instanceof LifeCycleListener) { + ((LifeCycleListener)endpointRegistry).start(); + } + + for (EndpointListener listener : listeners) { + endpointRegistry.addListener(listener); + } + endpointRegistries.put(key, endpointRegistry); + return endpointRegistry; + } + + public void stop() { + declarations.clear(); + for (EndpointRegistry endpointRegistry : endpointRegistries.values()) { + if (endpointRegistry instanceof LifeCycleListener) { + ((LifeCycleListener)endpointRegistry).stop(); + } + } + endpointRegistries.clear(); + listeners.clear(); + } + + public synchronized Collection getEndpointRegistries() { + return new ArrayList(endpointRegistries.values()); + } + + public synchronized void addListener(EndpointListener listener) { + listeners.add(listener); + for(EndpointRegistry registry: endpointRegistries.values()) { + registry.addListener(listener); + } + } + + public synchronized List getListeners() { + return listeners; + } + + public synchronized void removeListener(EndpointListener listener) { + listeners.remove(listener); + for(EndpointRegistry registry: endpointRegistries.values()) { + registry.removeListener(listener); + } + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java new file mode 100644 index 0000000000..bab83bad2d --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java @@ -0,0 +1,299 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.runtime.impl; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * An builder that takes endpoint references and resolves them. It either finds local + * service endpoints if they are available or asks the domain. The main function here + * is to perform binding and policy matching. + * This is a separate builder in case it is required by undresolved endpoints + * once the runtime has started. + * + * @version $Rev$ $Date$ + */ +public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { + + protected ExtensionPointRegistry extensionPoints; + protected AssemblyFactory assemblyFactory; + protected InterfaceContractMapper interfaceContractMapper; + private Monitor monitor; + + + public EndpointReferenceBinderImpl(ExtensionPointRegistry extensionPoints) { + this.extensionPoints = extensionPoints; + + FactoryExtensionPoint factories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + + UtilityExtensionPoint utils = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utils.getUtility(InterfaceContractMapper.class); + MonitorFactory monitorFactory = utils.getUtility(MonitorFactory.class); + monitor = monitorFactory.createMonitor(); + } + + + + /** + * Build a single endpoint reference + * + * @param endpoint + * @param monitor + */ + public boolean bind(EndpointRegistry endpointRegistry, EndpointReference endpointReference) { + Problem problem = null; + if ( endpointReference.getStatus() == EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED || + endpointReference.getStatus() == EndpointReference.RESOLVED_BINDING ) { + // The endpoint reference is already resolved to either + // a service endpoint local to this composite or it has + // a remote binding + + // still need to check that the callback endpoint is set correctly + if (hasCallback(endpointReference) && + endpointReference.getCallbackEndpoint() != null && + endpointReference.getCallbackEndpoint().isUnresolved() == true ){ + problem = selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService().getEndpoints()); + } + } else if (endpointReference.getStatus() == EndpointReference.WIRED_TARGET_FOUND_READY_FOR_MATCHING ){ + // The endpoint reference is already resolved to either + // a service endpoint but no binding was specified in the + // target URL and/or the policies have yet to be matched. + + problem = selectForwardEndpoint(endpointReference, + endpointReference.getTargetEndpoint().getService().getEndpoints()); + + if (problem == null && hasCallback(endpointReference)){ + problem = selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService().getEndpoints()); + } + + } else if (endpointReference.getStatus() == EndpointReference.WIRED_TARGET_NOT_FOUND || + endpointReference.getStatus() == EndpointReference.NOT_CONFIGURED){ + // The service is in a remote composite somewhere else in the domain + + // find the service in the endpoint registry + List endpoints = endpointRegistry.findEndpoint(endpointReference); + + if (endpoints.size() == 0) { + problem = monitor.createProblem(this.getClass().getName(), + "endpoint-validation-messages", + Problem.Severity.ERROR, + this, + "NoEndpointsFound", + endpointReference.toString()); + } + + problem = selectForwardEndpoint(endpointReference, + endpoints); + + if (problem == null && hasCallback(endpointReference)){ + problem = selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService().getEndpoints()); + } + } + + if (problem != null){ + monitor.problem(problem); + return false; + } + + if (endpointReference.getStatus() != EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED && + endpointReference.getStatus() != EndpointReference.RESOLVED_BINDING){ + problem = monitor.createProblem(this.getClass().getName(), + "endpoint-validation-messages", + Problem.Severity.ERROR, + this, + "EndpointReferenceCantBeMatched", + endpointReference.toString()); + monitor.problem(problem); + return false; + } + + return true; + + } + + private Problem selectForwardEndpoint(EndpointReference endpointReference, List endpoints) { + + Endpoint matchedEndpoint = null; + + if (endpointReference.getReference().getName().startsWith("$self$.")){ + // just select the first one and don't do any policy matching + matchedEndpoint = endpoints.get(0); + } else { + // find the first endpoint that matches this endpoint reference + for (Endpoint endpoint : endpoints){ + if (haveMatchingPolicy(endpointReference, endpoint)){ + matchedEndpoint = endpoint; + break; + } + } + } + + if (matchedEndpoint == null){ + return null; + } + + endpointReference.setTargetEndpoint(matchedEndpoint); + endpointReference.setBinding(endpointReference.getTargetEndpoint().getBinding()); + endpointReference.setStatus(EndpointReference.WIRED_TARGET_FOUND_AND_MATCHED); + endpointReference.setUnresolved(false); + + return null; + } + + private boolean hasCallback(EndpointReference endpointReference){ + if (endpointReference.getReference().getInterfaceContract() == null || + endpointReference.getReference().getInterfaceContract().getCallbackInterface() == null || + endpointReference.getReference().getName().startsWith("$self$.")){ + return false; + } else { + return true; + } + } + + private Problem selectCallbackEndpoint(EndpointReference endpointReference, List endpoints) { + + Problem problem = null; + + // find the first callback endpoint that matches a callback endpoint reference + // at the service + Endpoint matchedEndpoint = null; + match: + for ( EndpointReference callbackEndpointReference : endpointReference.getTargetEndpoint().getCallbackEndpointReferences()){ + for (Endpoint endpoint : endpoints){ + if (haveMatchingPolicy(callbackEndpointReference, endpoint)){ + matchedEndpoint = endpoint; + break match; + } + } + } + + if (matchedEndpoint == null){ + return null; + } + + endpointReference.setCallbackEndpoint(matchedEndpoint); + + return problem; + } + + // FIXME: [rfeng] This implementation is wrong. It is the responsibility of the policy language + // to compare the reference and service side setting to determine if they are compatible. Some of + // policies apply to the reference side only, some of the policies apply to the service side only, + // while others apply to both sides. Even for those policies that apply to both side, they can be + // independent or related. + private boolean haveMatchingPolicy(EndpointReference endpointReference, Endpoint endpoint){ + + /* + // if no policy sets or intents are present then they match + if ((endpointReference.getRequiredIntents().size() == 0) && + (endpoint.getRequiredIntents().size() == 0) && + (endpointReference.getPolicySets().size() == 0) && + (endpoint.getPolicySets().size() == 0)) { + return true; + } + + // if there are different numbers of intents + // then they don't match + if (endpointReference.getRequiredIntents().size() != + endpoint.getRequiredIntents().size()) { + return false; + } + + // if there are different numbers of policy sets + // then they don't match + if (endpointReference.getPolicySets().size() != + endpoint.getPolicySets().size()) { + return false; + } + + // check intents for compatibility + for(Intent intentEPR : endpointReference.getRequiredIntents()){ + boolean matched = false; + for (Intent intentEP : endpoint.getRequiredIntents()){ + if (intentEPR.getName().equals(intentEP.getName())){ + matched = true; + break; + } + } + if (matched == false){ + return false; + } + } + + // check policy sets for compatibility. The list of policy sets + // may be a subset of the list of intents as some of the intents + // may be directly provided. We can't just rely on intent compatibility + // as different policy sets might have been attached at each end to + // satisfy the listed intents + + // if all of the policy sets on the endpoint reference match a + // policy set on the endpoint then they match + for(PolicySet policySetEPR : endpointReference.getPolicySets()){ + boolean matched = false; + for (PolicySet policySetEP : endpoint.getPolicySets()){ + // find if there is a policy set with the same name + if (policySetEPR.getName().equals(policySetEP.getName())){ + matched = true; + break; + } + // find if the policies inside the policy set match the + // policies inside a policy set on the endpoint + + // TODO - need a policy specific matcher to do this + // so need a new extension point + + } + + if (matched == false){ + return false; + } + } + */ + + return true; + } + + public boolean isOutOfDate(EndpointRegistry endpointRegistry, EndpointReference endpointReference) { + Endpoint te = endpointReference.getTargetEndpoint(); + if (!te.isUnresolved() && te.getURI()!= null) { + List endpoints = endpointRegistry.findEndpoint(endpointReference); + return ! endpoints.contains(endpointReference.getTargetEndpoint()); + } + return false; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java new file mode 100644 index 0000000000..4674456925 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.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.sca.core.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Implements functionality common to scope contexts. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeContainer implements ScopeContainer { + protected Map> wrappers = new ConcurrentHashMap>(); + protected final Scope scope; + + protected RuntimeComponent component; + protected volatile int lifecycleState = UNINITIALIZED; + + + public AbstractScopeContainer(Scope scope, RuntimeComponent component) { + this.scope = scope; + this.component = component; + } + + protected void checkInit() { + if (getLifecycleState() != RUNNING) { + throw new IllegalStateException("Scope container not running [" + getLifecycleState() + "]"); + } + } + + /** + * Creates a new physical instance of a component, wrapped in an + * InstanceWrapper. + * + * @param component the component whose instance should be created + * @return a wrapped instance that has been injected but not yet started + * @throws TargetResolutionException if there was a problem creating the + * instance + */ + protected InstanceWrapper createInstanceWrapper() throws TargetResolutionException { + ImplementationProvider implementationProvider = component.getImplementationProvider(); + if (implementationProvider instanceof ScopedImplementationProvider) { + return ((ScopedImplementationProvider)implementationProvider).createInstanceWrapper(); + } + return null; + } + + public InstanceWrapper getAssociatedWrapper(KEY contextId) throws TargetResolutionException { + return getWrapper(contextId); // TODO: what is this method supposed to do diff than getWrapper? + } + + public Scope getScope() { + return scope; + } + + public InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException { + return wrappers.get(contextId); + } + + public void addWrapperReference(KEY existingContextId, KEY newContextId) + throws TargetResolutionException { + // do nothing here. the conversational scope container implements this + } + + public void registerWrapper(InstanceWrapper wrapper, KEY contextId) throws TargetResolutionException { + // do nothing here. the conversational scope container implements this + } + + protected boolean isEagerInit() { + ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider(); + if (implementationProvider instanceof ScopedImplementationProvider) { + return ((ScopedImplementationProvider)implementationProvider).isEagerInit(); + } + return false; + } + + public void returnWrapper(InstanceWrapper wrapper, KEY contextId) throws TargetDestructionException { + } + + /** + * Default implementation of remove which does nothing + * + * @param contextId the identifier of the context to remove. + */ + public void remove(KEY contextId) + throws TargetDestructionException { + } + + public synchronized void start() { + int lifecycleState = getLifecycleState(); + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + setLifecycleState(RUNNING); + } + + public void startContext(KEY contextId) { + if(isEagerInit()) { + try { + getWrapper(contextId); + } catch (TargetResolutionException e) { + // + } + } + } + + public synchronized void stop() { + int lifecycleState = getLifecycleState(); + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + setLifecycleState(STOPPED); + } + + public void stopContext(KEY contextId) { + wrappers.remove(contextId); + } + + @Override + public String toString() { + String s; + switch (lifecycleState) { + case ScopeContainer.CONFIG_ERROR: + s = "CONFIG_ERROR"; + break; + case ScopeContainer.ERROR: + s = "ERROR"; + break; + case ScopeContainer.INITIALIZING: + s = "INITIALIZING"; + break; + case ScopeContainer.INITIALIZED: + s = "INITIALIZED"; + break; + case ScopeContainer.RUNNING: + s = "RUNNING"; + break; + case ScopeContainer.STOPPING: + s = "STOPPING"; + break; + case ScopeContainer.STOPPED: + s = "STOPPED"; + break; + case ScopeContainer.UNINITIALIZED: + s = "UNINITIALIZED"; + break; + default: + s = "UNKNOWN"; + break; + } + return "In state [" + s + ']'; + } + + public RuntimeComponent getComponent() { + return component; + } + + public void setComponent(RuntimeComponent component) { + this.component = component; + } + + public int getLifecycleState() { + return lifecycleState; + } + + /** + * Set the current state of the Lifecycle. + * + * @param lifecycleState the new state + */ + protected void setLifecycleState(int lifecycleState) { + this.lifecycleState = lifecycleState; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java new file mode 100644 index 0000000000..2ea724ccf6 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.core.scope.impl.CompositeScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.impl.ScopeRegistryImpl; +import org.apache.tuscany.sca.core.scope.impl.StatelessScopeContainerFactory; + +/** + * A default scope registry implementation. + * + * @version $Rev$ $Date$ + */ +public class DefaultScopeRegistry extends ScopeRegistryImpl implements ScopeRegistry { + + public DefaultScopeRegistry() { + ScopeContainerFactory[] factories = + new ScopeContainerFactory[] {new CompositeScopeContainerFactory(), new StatelessScopeContainerFactory()}; + for (ScopeContainerFactory f : factories) { + register(f); + } + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java new file mode 100644 index 0000000000..0a7f2ef64f --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.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.sca.core.scope; + +/** + * The default implementation scopes supported by assemblies. + * + * @version $Rev$ $Date$ + */ +public class Scope { + public static final Scope STATELESS = new Scope("STATELESS"); + public static final Scope COMPOSITE = new Scope("COMPOSITE"); + public static final Scope INVALID = new Scope("INVALID"); + + private String scope; + + public Scope(String scope) { + this.scope = scope.toUpperCase().intern(); + } + + public String getScope() { + return scope; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Scope scope1 = (Scope) o; + return !(scope != null ? scope != scope1.scope.intern() : scope1.scope != null); + } + + @Override + public int hashCode() { + return scope != null ? scope.hashCode() : 0; + } + + @Override + public String toString() { + return scope; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java new file mode 100644 index 0000000000..2398ecea3e --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.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.sca.core.scope; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * Manages the lifecycle and visibility of instances associated with a an {@link RuntimeComponent}. + * + * @version $Rev$ $Date$ + * @param the type of IDs that this container uses to identify its contexts. + * For example, for COMPOSITE scope this could be the URI of the composite component, + * or for HTTP Session scope it might be the HTTP session ID. + */ +public interface ScopeContainer { + + /** + * Returns the Scope that this container supports. + * + * @return the Scope that this container supports + */ + Scope getScope(); + + /** + * Start a new context with the supplied ID. + * + * @param contextId an ID that uniquely identifies the context. + */ + void startContext(KEY contextId); + + /** + * Stop the context with the supplied ID. + * + * @param contextId an ID that uniquely identifies the context. + */ + void stopContext(KEY contextId); + + /** + * Returns an instance wrapper associated with the current scope context, creating one if necessary + * @param contextId the id for the scope context + * + * @return the wrapper for the target instance + * @throws TargetResolutionException if there was a problem instantiating the target instance + */ + InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException; + + /** + * Allows a component to be registered against more than one context id. This is required in the + * case of stateful callbacks where we want to identify the originating client component instance + * as the callback target but we don't want to reuse the clients original conversation id + * + * @param existingContextId an id that identifies an existing component instance + * @param newContextId a new id against which this component will also be registered + * @throws TargetResolutionException + */ + void addWrapperReference(KEY existingContextId, KEY newContextId) + throws TargetResolutionException; + + /** + * Register an existing instance against a context id. This is needed + * for a stateful callback where the service reference for the forward call + * contains a callback object that is not a service reference. + * + * @param wrapper the instance wrapper for the instance to be registered + * @param contextId the id for the scope context + * @throws TargetResolutionException + */ + void registerWrapper(InstanceWrapper wrapper, KEY contextId) + throws TargetResolutionException; + + /** + * Returns an implementation instance associated with the current scope context. + * If no instance is found, a {@link TargetNotFoundException} is thrown. + * @param contextId the id for the scope context + * + * @return the wrapper for the target instance + * @throws TargetResolutionException if there was a problem instantiating the target instance + */ + InstanceWrapper getAssociatedWrapper(KEY contextId) + throws TargetResolutionException; + + /** + * Return a wrapper after use (for example, after invoking the instance). + * @param wrapper the wrapper for the target instance being returned + * @param contextId the id for the scope context + * + * @throws TargetDestructionException if there was a problem returning the target instance + */ + void returnWrapper(InstanceWrapper wrapper, KEY contextId) + throws TargetDestructionException; + + /** + * Removes an identified component implementation instance associated with the current + * context from persistent storage + * + * @param contextId the identifier of the context to remove. + */ + void remove(KEY contextId) + throws TargetDestructionException; + + /* A configuration error state */ + int CONFIG_ERROR = -1; + /* Has not been initialized */ + int UNINITIALIZED = 0; + /* In the process of being configured and initialized */ + int INITIALIZING = 1; + /* Instantiated and configured */ + int INITIALIZED = 2; + /* Configured and initialized */ + int RUNNING = 4; + /* In the process of being shutdown */ + int STOPPING = 5; + /* Has been shutdown and removed from the composite */ + int STOPPED = 6; + /* In an error state */ + int ERROR = 7; + + /** + * Returns the lifecycle state + * + * @see #UNINITIALIZED + * @see #INITIALIZING + * @see #INITIALIZED + * @see #RUNNING + * @see #STOPPING + * @see #STOPPED + */ + int getLifecycleState(); + + /** + * Starts the Lifecycle. + */ + void start(); + + /** + * Stops the Lifecycle. + */ + void stop(); + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java new file mode 100644 index 0000000000..b19c14b3e0 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.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.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Factory to create ScopeContainer for components + * + * @version $Rev$ $Date$ + */ +public interface ScopeContainerFactory { + ScopeContainer createScopeContainer(RuntimeComponent component); + Scope getScope(); +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java new file mode 100644 index 0000000000..842ed4c547 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * Manages {@link ScopeContainer}s in the runtime + * + * @version $Rev$ $Date$ + */ +public interface ScopeRegistry { + + /** + * Returns the scope container for the given scope or null if one not found + * + * @param scope the scope + * @return the scope container for the given scope or null if one not found + */ + ScopeContainer getScopeContainer(RuntimeComponent component); + + /** + * @param factory + */ + void register(ScopeContainerFactory factory); +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java new file mode 100644 index 0000000000..30d5c77181 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.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.sca.core.scope; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.provider.ImplementationProvider; + +/** + * A component implementation can implement this interface to provide scope + * management for the components + * + * @version $Rev$ $Date$ + */ +public interface ScopedImplementationProvider extends ImplementationProvider { + /** + * Get the scope for the component implementation + * + * @return The scope for the component implementation, if null is returned, + * STATELESS will be used + */ + Scope getScope(); + + /** + * Indicate if the component needs to be eagerly initialized + * + * @return true if the component is marked to be eagerly initialized, false + * otherwise + */ + boolean isEagerInit(); + + /** + * @return the maxAge + */ + long getMaxAge(); + + /** + * @return the maxIdleTime + */ + long getMaxIdleTime(); + + /** + * Create a wrapper for the component instance for the scope management + * + * @return A wrapper for the component instance + */ + InstanceWrapper createInstanceWrapper(); + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java new file mode 100644 index 0000000000..c27b112f8a --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Scoped runtime component + * + * @version $Rev$ $Date$ + */ +public interface ScopedRuntimeComponent extends RuntimeComponent { + /** + * Set the associated scope container + * @param scopeContainer + */ + void setScopeContainer(ScopeContainer scopeContainer); + /** + * Get the assoicated scope container + * @return + */ + ScopeContainer getScopeContainer(); +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java new file mode 100644 index 0000000000..0f83dad97d --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Denotes an error destroying a target + * + * @version $Rev$ $Date$ + */ +public class TargetDestructionException extends TargetResolutionException { + private static final long serialVersionUID = -6126684147851674709L; + + public TargetDestructionException() { + super(); + } + + public TargetDestructionException(String message, Throwable cause) { + super(message, cause); + } + + public TargetDestructionException(String message) { + super(message); + } + + public TargetDestructionException(Throwable cause) { + super(cause); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java new file mode 100644 index 0000000000..15959c0608 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Denotes an error initializing a target + * + * @version $Rev$ $Date$ + */ +public class TargetInitializationException extends TargetResolutionException { + private static final long serialVersionUID = -6228778208649752698L; + + public TargetInitializationException() { + super(); + } + + public TargetInitializationException(String message, Throwable cause) { + super(message, cause); + } + + public TargetInitializationException(String message) { + super(message); + } + + public TargetInitializationException(Throwable cause) { + super(cause); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java new file mode 100644 index 0000000000..bb46a2499b --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Thrown when a target of an operation cannot be found + * + * @version $Rev$ $Date$ + */ +public class TargetNotFoundException extends TargetResolutionException { + private static final long serialVersionUID = 5541830480658471186L; + + public TargetNotFoundException() { + super(); + } + + public TargetNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public TargetNotFoundException(String message) { + super(message); + } + + public TargetNotFoundException(Throwable cause) { + super(cause); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java new file mode 100644 index 0000000000..ea8d0e876c --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Denotes an error retrieving a target instance + * + * @version $Rev$ $Date$ + */ +public class TargetResolutionException extends Exception { + private static final long serialVersionUID = 2912513650522019405L; + + public TargetResolutionException() { + super(); + } + + public TargetResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public TargetResolutionException(String message) { + super(message); + } + + public TargetResolutionException(Throwable cause) { + super(cause); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java new file mode 100644 index 0000000000..730f92e0f9 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope.impl; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.AbstractScopeContainer; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetNotFoundException; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ServiceUnavailableException; + +/** + * A scope context which manages atomic component instances keyed by composite + * + * @version $Rev$ $Date$ + */ +public class CompositeScopeContainer extends AbstractScopeContainer { + private InstanceWrapper wrapper; + + public CompositeScopeContainer(RuntimeComponent component) { + super(Scope.COMPOSITE, component); + } + + @Override + public synchronized void stop() { + super.stop(); + if (wrapper != null) { + try { + wrapper.stop(); + } catch (TargetDestructionException e) { + throw new IllegalStateException(e); + } + } + wrapper = null; + } + + @Override + public synchronized InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException { + if (wrapper == null) { + try { + wrapper = createInstanceWrapper(); + wrapper.start(); + } catch (Exception e) { + throw new ServiceUnavailableException(e); + } + } + return wrapper; + } + + @Override + public InstanceWrapper getAssociatedWrapper(KEY contextId) throws TargetResolutionException { + if (wrapper == null) { + throw new TargetNotFoundException(component.getURI()); + } + return wrapper; + } + + @Override + public synchronized void start() { + super.start(); + if (isEagerInit()) { + try { + getWrapper(null); + } catch (TargetResolutionException e) { + throw new IllegalStateException(e); + } + } + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java new file mode 100644 index 0000000000..f61e70a598 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope.impl; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new CompositeScopeContainer(component); + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java new file mode 100644 index 0000000000..9884c5f053 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.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.sca.core.scope.impl; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * The default implementation of a scope registry + * + * @version $Rev$ $Date$ + */ +public class ScopeRegistryImpl implements ScopeRegistry { + private final Map scopeCache = new ConcurrentHashMap(); + + public void register(ScopeContainerFactory factory) { + scopeCache.put(factory.getScope(), factory); + } + + public ScopeContainer getScopeContainer(RuntimeComponent runtimeComponent) { + if (!(runtimeComponent instanceof ScopedRuntimeComponent)) { + return null; + } + ScopedRuntimeComponent component = (ScopedRuntimeComponent)runtimeComponent; + if (component.getScopeContainer() != null) { + return component.getScopeContainer(); + } + ImplementationProvider implementationProvider = component.getImplementationProvider(); + if (implementationProvider instanceof ScopedImplementationProvider) { + ScopedImplementationProvider provider = (ScopedImplementationProvider)implementationProvider; + Scope scope = provider.getScope(); + if (scope == null) { + scope = Scope.STATELESS; + } else if (scope.equals(Scope.INVALID)) { + return null; + } + ScopeContainerFactory factory = scopeCache.get(scope); + ScopeContainer container = factory.createScopeContainer(component); + component.setScopeContainer(container); + return container; + } + return null; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java new file mode 100644 index 0000000000..1235fd2a67 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.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.sca.core.scope.impl; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.AbstractScopeContainer; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A scope context which manages stateless atomic component instances in a non-pooled fashion. + * + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainer extends AbstractScopeContainer { + + public StatelessScopeContainer(RuntimeComponent component) { + super(Scope.STATELESS, component); + } + + @Override + public InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException { + if (lifecycleState != RUNNING) { + throw new TargetResolutionException("scope container not running, lifecycleState=" + lifecycleState); + } + InstanceWrapper ctx = createInstanceWrapper(); + ctx.start(); + return ctx; + } + + @Override + public InstanceWrapper getAssociatedWrapper(KEY contextId) + throws TargetResolutionException { + return getWrapper(contextId); + } + + @Override + public void returnWrapper(InstanceWrapper wrapper, KEY contextId) + throws TargetDestructionException { + wrapper.stop(); + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java new file mode 100644 index 0000000000..5bf20a6a5f --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope.impl; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new StatelessScopeContainer(component); + } + + public Scope getScope() { + return Scope.STATELESS; + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java new file mode 100644 index 0000000000..9e6f3b3087 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.work.NotificationListener; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.apache.tuscany.sca.work.WorkSchedulerException; + +/** + * A work scheduler implementation based on a JSR 237 work manager. + *

+ *

+ * 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 implementation available. For example, if the managed environment supports work manager the runtime can use + * the appropriate lookup mechanism to inject the work manager implementation.

+ * + * @version $Rev$ $Date$ + */ +public class DefaultWorkScheduler implements WorkScheduler, LifeCycleListener { + + /** + * Underlying JSR-237 work manager + */ + private ThreadPoolWorkManager jsr237WorkManager; + + /** + * Initializes the JSR 237 work manager. + * + * @param jsr237WorkManager JSR 237 work manager. + */ + public DefaultWorkScheduler() { + } + + private synchronized ThreadPoolWorkManager getWorkManager() { + if (jsr237WorkManager != null) { + return jsr237WorkManager; + } +// try { +// InitialContext ctx = new InitialContext(); +// jsr237WorkManager = (ThreadPoolWorkManager)ctx.lookup("java:comp/env/wm/TuscanyWorkManager"); +// } catch (Throwable e) { +// // ignore +// } + if (jsr237WorkManager == null) { + jsr237WorkManager = new ThreadPoolWorkManager(0); + } + return 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 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 void scheduleWork(T work, NotificationListener listener) { + + if (work == null) { + throw new IllegalArgumentException("Work cannot be null"); + } + + Work jsr237Work = new Work(work); + try { + if (listener == null) { + getWorkManager().schedule(jsr237Work); + } else { + Jsr237WorkListener jsr237WorkListener = new Jsr237WorkListener(listener, work); + getWorkManager().schedule(jsr237Work, jsr237WorkListener); + } + } catch (IllegalArgumentException ex) { + if (listener != null) { + listener.workRejected(work); + } else { + throw new WorkSchedulerException(ex); + } + } catch (Exception ex) { + throw new WorkSchedulerException(ex); + } + + } + + public void start() { + } + + public void stop() { + if (jsr237WorkManager instanceof ThreadPoolWorkManager) { + // Allow privileged access to modify threads. Requires RuntimePermission in security + // policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ((ThreadPoolWorkManager)jsr237WorkManager).destroy(); + return null; + } + }); + } + } + + /* + * WorkListener for keeping track of work status callbacks. + * + */ + private class Jsr237WorkListener implements WorkListener { + + // Notification listener + private NotificationListener listener; + + // Work + private T work; + + /* + * Initializes the notification listener. + */ + public Jsr237WorkListener(NotificationListener 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; + } + + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java new file mode 100644 index 0000000000..e7728ca9a9 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; + +import org.apache.tuscany.sca.work.WorkSchedulerException; + +/** + * A thread-pool based implementation for the JSR-237 work manager. + *

+ *

+ * This implementation supports only local work. + *

+ * TODO Elaborate the implementation.

+ * + * @version $Rev$ $Date$ + */ +public class ThreadPoolWorkManager { + + // Map of work items currently handled by the work manager + private Map workItems = new ConcurrentHashMap(); + + // Thread-pool + private ExecutorService executor; + + /** + * Initializes the thread-pool. + * + * @param threadPoolSize Thread-pool size. If the size <1, then a cached pool is created + */ + public ThreadPoolWorkManager(int threadPoolSize) { + ThreadFactory factory = new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setDaemon(true); + return thread; + } + }; + if (threadPoolSize <= 0) { + + // Creates a new Executor, use a custom ThreadFactory that + // creates daemon threads. + executor = Executors.newCachedThreadPool(factory); + } else { + 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 IllegalArgumentException { + 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 IllegalArgumentException { + + WorkItem workItem = new WorkItem(UUID.randomUUID().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 WorkEvent(workItem)); + } + throw new IllegalArgumentException("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 acceptance. + * + * @param workItem Work item representing the work that was accepted. + * @param work Work that was accepted. + */ + private void workAccepted(final WorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_ACCEPTED); + WorkEvent event = new WorkEvent(workItem); + listener.workAccepted(event); + } + } + + /* + * Method to indicate a work start. + */ + private void workStarted(final WorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_STARTED); + WorkEvent event = new WorkEvent(workItem); + listener.workStarted(event); + } + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final WorkItem workItem, final Work work) { + workCompleted(workItem, work, null); + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final WorkItem workItem, final Work work, final WorkSchedulerException exception) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_COMPLETED); + workItem.setResult(work); + workItem.setException(exception); + WorkEvent event = new WorkEvent(workItem); + listener.workCompleted(event); + workItems.remove(workItem); + } + } + + /* + * Schedules the work using the ThreadPool. + */ + private boolean scheduleWork(final Work work, final WorkItem 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 WorkItem workItem; + + // The original work. + private Work decoratedWork; + + /* + * Initializes the work item and underlying work. + */ + private DecoratingWork(final WorkItem 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 WorkSchedulerException(th.getMessage(), th)); + } + } + + } + + public void destroy() { + executor.shutdown(); + } + +} + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java new file mode 100644 index 0000000000..ca06d0e854 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.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.sca.core.work.impl; + +/** + * JCA work wrapper. + * + * @version $Rev$ $Date$ + */ +public class Work { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public Work(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(); + } +} \ No newline at end of file diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java new file mode 100644 index 0000000000..4580011806 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.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.sca.core.work.impl; + +import org.apache.tuscany.sca.work.WorkSchedulerException; + + + +/** + * Default immutable implementation of the WorkEvent class. + * + * @version $Rev$ $Date$ + */ +class WorkEvent { + + public static final int WORK_ACCEPTED = 1; + public static final int WORK_REJECTED = 2; + public static final int WORK_STARTED = 3; + public static final int WORK_COMPLETED = 4; + + // Work item for this event + private WorkItem workItem; + + // Exception if something has gone wrong + private WorkSchedulerException exception; + + /** + * Instantiates the event. + * + * @param workItem Work item for this event. + */ + public WorkEvent(final WorkItem 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 WorkSchedulerException getException() { + return exception; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java new file mode 100644 index 0000000000..0fc104d0fc --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.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.sca.core.work.impl; + +import org.apache.tuscany.sca.work.WorkSchedulerException; + +/** + * An identity based immutable implementation of the WorkItem + * interface. + * + * @version $Rev$ $Date$ + */ +class 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 WorkSchedulerException exception; + + /** + * Instantiates an id for this item. + * + * @param id of this work event. + */ + protected WorkItem(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() { + 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 WorkSchedulerException getException() { + return exception; + } + + /** + * Sets the exception. + * + * @param exception Exception. + */ + protected void setException(final WorkSchedulerException 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() + */ + @Override + 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.. + */ + @Override + public boolean equals(final Object obj) { + return (obj != null) && (obj.getClass() == WorkItem.class) && ((WorkItem) 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() != WorkItem.class) { + throw new ClassCastException(o.getClass().getName()); + } else { + return ((WorkItem) o).getId().compareTo(getId()); + } + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java new file mode 100644 index 0000000000..38bbaeebe0 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.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.sca.core.work.impl; + +public interface WorkListener { + + long IMMEDIATE = 0; + long INDEFINITE = java.lang.Long.MAX_VALUE; + + void workAccepted(WorkEvent event); + void workCompleted(WorkEvent event); + void workRejected(WorkEvent event); + void workStarted(WorkEvent event); + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory new file mode 100644 index 0000000000..e8ee318b6c --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# Set the ranking to be greater than the DefaultAssemblyFactory +org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;ranking=100 diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory new file mode 100644 index 0000000000..51ed2449fb --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +org.apache.tuscany.sca.core.context.DefaultComponentContextFactory diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory new file mode 100644 index 0000000000..70b17a2f00 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +org.apache.tuscany.sca.core.context.DefaultRequestContextFactory diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..94c83ceeab --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Implementation class for the artifact processor extension +org.apache.tuscany.sca.core.assembly.impl.ReferenceParameterProcessor;qname=http://tuscany.apache.org/xmlns/sca/1.1#referenceParameters,model=org.apache.tuscany.sca.runtime.ReferenceParameters + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint new file mode 100644 index 0000000000..c6567aa904 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.tuscany.sca.core.invocation.DefaultProxyFactoryExtensionPoint + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry new file mode 100644 index 0000000000..2aa000efc0 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.tuscany.sca.core.scope.DefaultScopeRegistry + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory new file mode 100644 index 0000000000..a21b75b570 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.tuscany.sca.core.invocation.impl.MessageFactoryImpl + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator new file mode 100644 index 0000000000..0182f52086 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.tuscany.sca.core.assembly.impl.CompositeActivatorImpl + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory new file mode 100644 index 0000000000..c5c7e543ac --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +org.apache.tuscany.sca.core.runtime.DefaultDomainRegistryFactory + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder new file mode 100644 index 0000000000..61edf5111e --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +org.apache.tuscany.sca.core.runtime.impl.EndpointReferenceBinderImpl + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry new file mode 100644 index 0000000000..9ca8971396 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointRegistry @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.tuscany.sca.core.assembly.impl.EndpointRegistryImpl;ranking=100,scheme=vm diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer new file mode 100644 index 0000000000..fb951e75d5 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +org.apache.tuscany.sca.core.assembly.impl.EndpointSerializerImpl diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler new file mode 100644 index 0000000000..576e52d8ea --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +org.apache.tuscany.sca.core.work.impl.DefaultWorkScheduler + diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/endpoint-validation-messages.properties b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/endpoint-validation-messages.properties new file mode 100644 index 0000000000..7be0f2b4a2 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/main/resources/endpoint-validation-messages.properties @@ -0,0 +1,22 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# +NoEndpointsFound = No endpoints found in the domain that match the reference {0} +EndpointReferenceCantBeMatched = = Unable to match the endpoint reference {0} with the policy of the service to which it refers. diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java new file mode 100644 index 0000000000..1302bed681 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.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.sca.core.invocation.impl; + +import static org.junit.Assert.assertEquals; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.Phase; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class InvocationChainImplTestCase { + + @Test + public void testInsertAtEnd() throws Exception { + Operation op = newOperation("foo"); + InvocationChain chain = new InvocationChainImpl(op, op, true, new PhaseManager(new DefaultExtensionPointRegistry())); + Interceptor inter2 = new MockInterceptor(); + Interceptor inter1 = new MockInterceptor(); + chain.addInterceptor(inter1); + chain.addInterceptor(inter2); + Interceptor head = (Interceptor)chain.getHeadInvoker(); + assertEquals(inter1, head); + assertEquals(inter2, head.getNext()); + } + + @Test + public void testAddByPhase() throws Exception { + Operation op = newOperation("foo"); + InvocationChain chain = new InvocationChainImpl(op, op, false, new PhaseManager(new DefaultExtensionPointRegistry())); + Interceptor inter1 = new MockInterceptor(); + Interceptor inter2 = new MockInterceptor(); + Interceptor inter3 = new MockInterceptor(); + Interceptor inter4 = new MockInterceptor(); + chain.addInterceptor(inter3); // SERVICE + chain.addInterceptor(Phase.IMPLEMENTATION_POLICY, inter4); + chain.addInterceptor(Phase.SERVICE_POLICY, inter2); + chain.addInterceptor(Phase.SERVICE_BINDING, inter1); + Interceptor head = (Interceptor)chain.getHeadInvoker(); + assertEquals(inter1, head); + assertEquals(inter2, inter1.getNext()); + assertEquals(inter3, inter2.getNext()); + assertEquals(inter4, inter3.getNext()); + } + + private class MockInterceptor implements Interceptor { + + private Invoker next; + + public Message invoke(Message msg) { + return null; + } + + public void setNext(Invoker next) { + this.next = next; + } + + public Invoker getNext() { + return next; + } + + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java new file mode 100644 index 0000000000..8fcead004d --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.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.sca.core.invocation.impl; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class PhaseManagerTestCase { + + @Test + public void testDiscovery() { + PhaseManager pm = new PhaseManager("org.apache.tuscany.sca.invocation.PhaseTest"); + List phases = pm.getAllPhases(); + System.out.println(phases.size()); + System.out.println(phases); + // Assert.assertEquals(15, phases.size()); + Assert.assertEquals("reference.first", phases.get(0)); + + int rt = phases.indexOf("reference.transaction"); + Assert.assertTrue(rt > phases.indexOf("reference.interface")); + + int st = phases.indexOf("service.transaction"); + Assert.assertTrue(st > phases.indexOf("service.binding")); + + int it = phases.indexOf("implementation.transaction"); + Assert.assertTrue(it < phases.indexOf("implementation.policy")); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java new file mode 100644 index 0000000000..c268e133e4 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.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.sca.core.invocation.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class PhaseSorterTestCase { + private PhaseSorter graph; + + @Before + public void setUp() throws Exception { + graph = new PhaseSorter(); + } + + @Test + public void testSort() { + graph.addEdge("a", "b"); + graph.addEdge("a", "c"); + graph.addEdge("c", "d"); + graph.addEdge("b", "c"); + List order = graph.topologicalSort(true); + assertEquals(Arrays.asList("a", "b", "c", "d"), order); + assertTrue(!graph.getVertices().isEmpty()); + + graph.addEdge("d", "a"); + try { + order = graph.topologicalSort(true); + assertTrue("Should have failed", false); + } catch (IllegalArgumentException e) { + assertTrue(true); + } + + graph.removeEdge("d", "a"); + order = graph.topologicalSort(false); + assertEquals(Arrays.asList("a", "b", "c", "d"), order); + assertTrue(graph.getVertices().isEmpty()); + } + + @After + public void tearDown() throws Exception { + } + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java new file mode 100644 index 0000000000..16ca5fd00e --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + + + +/** + * Simple Work item that will throw an exception + * + * @version $Rev$ $Date$ + */ +public class FailingWork extends Work { + + public FailingWork() { + super(null); + } + + /** + * {@inheritDoc} + */ + public boolean isDaemon() { + return false; + } + + /** + * {@inheritDoc} + */ + public void release() { + } + + /** + * Throws an IllegalArgumentException + */ + public void run() { + System.out.println("Starting " + this + " and throwing an Exception"); + throw new IllegalArgumentException("Sample exception from " + this); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java new file mode 100644 index 0000000000..2d791e5012 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +/** + * Simple Runnable that throws an IllegalArgumentException + * + * @version $Rev$ $Date$ + */ +public class JSR237MyFailingRunnable extends JSR237MyRunnable { + + /** + * Constructor + */ + public JSR237MyFailingRunnable() { + super(-1); + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + @Override + public void run() { + System.out.println("Starting " + this + " and throwing an Exception"); + throw new IllegalArgumentException("Sample exception from " + this); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java new file mode 100644 index 0000000000..c0183b6f9b --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple Runnable that is used for testing Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class JSR237MyRunnable implements Runnable { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger runCompletedCount = new AtomicInteger(); + + /** + * The amount of time to sleep in the Run loop + */ + private final long sleepTime; + + /** + * Constructor + * + * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method + */ + public JSR237MyRunnable(long sleepTime) { + this.sleepTime = sleepTime; + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + public void run() { + System.out.println("Starting " + this); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Done " + this); + runCompletedCount.incrementAndGet(); + } + + /** + * Returns the number of completed calls to run() + * + * @return The number of completed calls to run() + */ + public int getRunCompletedCount() { + return runCompletedCount.get(); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java new file mode 100644 index 0000000000..307f24aca7 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tuscany.sca.work.NotificationListener; + +/** + * Simple NotificationListener that is used for testing Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class JSR237MyRunnerListener implements NotificationListener { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger workAcceptedCallCount = new AtomicInteger(); + + /** + * Count of workStarted() method calls + */ + private AtomicInteger workStartedCallCount = new AtomicInteger(); + + /** + * Count of workCompleted() method calls + */ + private AtomicInteger workCompletedCallCount = new AtomicInteger(); + + /** + * Count of workFailed() method calls + */ + private AtomicInteger workFailedCallCount = new AtomicInteger(); + + /** + * Count of workRejected() method calls + */ + private AtomicInteger workRejectedCallCount = new AtomicInteger(); + + /** + * List of all exceptions thrown by Work items + */ + private List workExceptions = Collections.synchronizedList(new ArrayList()); + + /** + * {@inheritDoc} + */ + public void workAccepted(JSR237MyRunnable work) { + workAcceptedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workCompleted(JSR237MyRunnable work) { + workCompletedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workFailed(JSR237MyRunnable work, Throwable error) { + workExceptions.add(error); + workFailedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workRejected(JSR237MyRunnable work) { + workRejectedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workStarted(JSR237MyRunnable work) { + workStartedCallCount.incrementAndGet(); + } + + /** + * Returns the number of calls to workAccepted() + * + * @return The number of calls to workAccepted() + */ + public int getWorkAcceptedCallCount() { + return workAcceptedCallCount.get(); + } + + /** + * Returns the number of calls to workStarted() + * + * @return The number of calls to workStarted() + */ + public int getWorkStartedCallCount() { + return workStartedCallCount.get(); + } + + /** + * Returns the number of calls to workCompleted() + * + * @return The number of calls to workCompleted() + */ + public int getWorkCompletedCallCount() { + return workCompletedCallCount.get(); + } + + /** + * Returns the number of calls to workFailed() + * + * @return The number of calls to workFailed() + */ + public int getWorkFailedCallCount() { + return workFailedCallCount.get(); + } + + /** + * Returns the number of calls to workRejected() + * + * @return The number of calls to workRejected() + */ + public int getWorkRejectedCallCount() { + return workRejectedCallCount.get(); + } + + /** + * Returns a List of all exceptions that are thrown by the Work items + * + * @return A List of all exceptions that are thrown by the Work items + */ + public List getWorkExceptions() { + return Collections.unmodifiableList(workExceptions); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java new file mode 100644 index 0000000000..c0f35d427c --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Test case for Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class Jsr237WorkSchedulerTestCase { + + /** + * Wait up to 20 seconds for the Work units to complete + */ + private static final long WAIT_TIMEOUT = 20000; + + /** + * This is the shared instance of the ThreadPoolWorkManager used by the tests + */ + private static DefaultWorkScheduler workSchedular = null; + + /** + * Setup the Jsr237WorkScheduler + */ + @BeforeClass + public static void setup() { + workSchedular = new DefaultWorkScheduler(); + } + + /** + * Make sure that the Jsr237WorkScheduler is stopped after running the tests + */ + @AfterClass + public static void destroy() { + if (workSchedular != null) { + workSchedular.stop(); + } + } + + /** + * Tests running a single fast job on the Jsr237WorkScheduler + */ + @Test + public void testSingleFastJob() { + // Create the work and register it + JSR237MyRunnable fast = new JSR237MyRunnable(10); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that fails on the Jsr237WorkScheduler + */ + @Test + public void testSingleFailingJob() { + // Create the work and register it + JSR237MyFailingRunnable fail = new JSR237MyFailingRunnable(); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fail, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(0, listener.getWorkCompletedCallCount()); + Assert.assertEquals(1, listener.getWorkFailedCallCount()); + Assert.assertEquals(1, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs on the Jsr237WorkScheduler + */ + @Test + public void testMultipleJobs() { + // Create the work and register it + JSR237MyRunnable fast1 = new JSR237MyRunnable(5); + JSR237MyRunnable fast2 = new JSR237MyRunnable(10); + JSR237MyRunnable fast3 = new JSR237MyRunnable(20); + JSR237MyRunnable slow1= new JSR237MyRunnable(200); + JSR237MyRunnable slow2 = new JSR237MyRunnable(200); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast1, listener); + workSchedular.scheduleWork(fast2, listener); + workSchedular.scheduleWork(fast3, listener); + workSchedular.scheduleWork(slow1, listener); + workSchedular.scheduleWork(slow2, listener); + + // Wait for the 5 jobs to complete + waitForWorkToComplete(listener, 5); + + // Test that the job completed successfully. + Assert.assertEquals(5, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(5, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs some of which fail on the + * Jsr237WorkScheduler + */ + @Test + public void testMultipleJobsSomeFail() { + // Create the work and register it + JSR237MyRunnable fast1 = new JSR237MyRunnable(5); + JSR237MyRunnable fast2 = new JSR237MyRunnable(10); + JSR237MyRunnable fast3 = new JSR237MyRunnable(20); + JSR237MyRunnable slow1= new JSR237MyRunnable(200); + JSR237MyRunnable slow2 = new JSR237MyRunnable(200); + JSR237MyFailingRunnable fail1 = new JSR237MyFailingRunnable(); + JSR237MyFailingRunnable fail2 = new JSR237MyFailingRunnable(); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast1, listener); + workSchedular.scheduleWork(fast2, listener); + workSchedular.scheduleWork(fail1, listener); + workSchedular.scheduleWork(fast3, listener); + workSchedular.scheduleWork(slow1, listener); + workSchedular.scheduleWork(fail2, listener); + workSchedular.scheduleWork(slow2, listener); + + // Wait for the 7 jobs to complete + waitForWorkToComplete(listener, 7); + + // Test that the job completed successfully. + Assert.assertEquals(7, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(7, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(2, listener.getWorkFailedCallCount()); + Assert.assertEquals(2, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that has no listener + */ + @Test + public void testSingleFastJobWithNoListener() { + // Create the work and register it + JSR237MyRunnable fast = new JSR237MyRunnable(10); + workSchedular.scheduleWork(fast); + + // Wait for the job to complete + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = fast.getRunCompletedCount(); + if (completedCount == 1) { + break; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for the job to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } + + /** + * Tests scheduling a null as the work item + */ + @Test + public void testNullWork() { + try { + workSchedular.scheduleWork(null); + Assert.fail("Should have thrown IllegalArgumentException "); + } catch (IllegalArgumentException ex) { + // As expected + Assert.assertTrue(ex.toString().indexOf("null") != -1); + } + } + + /** + * Waits for the specified number of jobs to complete or the timeout to fire. + * + * @param listener The listener to use to track Work unit completion + * @param completedWorkItemsToWaitFor The number of Work items to complete + */ + private void waitForWorkToComplete(JSR237MyRunnerListener listener, int completedWorkItemsToWaitFor) { + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = listener.getWorkCompletedCallCount() + listener.getWorkFailedCallCount(); + if (completedCount == completedWorkItemsToWaitFor) { + return; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for more jobs to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java new file mode 100644 index 0000000000..a452d6f371 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tuscany.sca.work.WorkSchedulerException; +import org.junit.Assert; + +/** + * A simple WorkListener that tracks invocations to it. + * + * @version $Rev$ $Date$ + */ +public class TestWorkListener implements WorkListener { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger workAcceptedCallCount = new AtomicInteger(); + + /** + * Count of workStarted() method calls + */ + private AtomicInteger workStartedCallCount = new AtomicInteger(); + + /** + * Count of workCompleted() method calls + */ + private AtomicInteger workCompletedCallCount = new AtomicInteger(); + + /** + * Count of workRejected() method calls + */ + private AtomicInteger workRejectedCallCount = new AtomicInteger(); + + /** + * List of all exceptions thrown by Work items + */ + private List workExceptions = Collections.synchronizedList(new ArrayList()); + + /** + * {@inheritDoc} + */ + public void workAccepted(WorkEvent work) { + workAcceptedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_ACCEPTED, work.getType()); + } + + /** + * {@inheritDoc} + */ + public void workStarted(WorkEvent work) { + workStartedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_STARTED, work.getType()); + } + + /** + * {@inheritDoc} + */ + public void workCompleted(WorkEvent work) { + if (work.getException() != null) { + workExceptions.add(work.getException()); + } + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_COMPLETED, work.getType()); + + workCompletedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workRejected(WorkEvent work) { + workRejectedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_REJECTED, work.getType()); + } + + /** + * Returns the number of calls to workAccepted() + * + * @return The number of calls to workAccepted() + */ + public int getWorkAcceptedCallCount() { + return workAcceptedCallCount.get(); + } + + /** + * Returns the number of calls to workStarted() + * + * @return The number of calls to workStarted() + */ + public int getWorkStartedCallCount() { + return workStartedCallCount.get(); + } + + /** + * Returns the number of calls to workCompleted() + * + * @return The number of calls to workCompleted() + */ + public int getWorkCompletedCallCount() { + return workCompletedCallCount.get(); + } + + /** + * Returns the number of calls to workRejected() + * + * @return The number of calls to workRejected() + */ + public int getWorkRejectedCallCount() { + return workRejectedCallCount.get(); + } + + /** + * Returns a List of all exceptions that are thrown by the Work items + * + * @return A List of all exceptions that are thrown by the Work items + */ + public List getWorkExceptions() { + return Collections.unmodifiableList(workExceptions); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java new file mode 100644 index 0000000000..122609d7e6 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * This test case will test the ThreadPoolWorkManager + * + * @version $Rev$ $Date$ + */ +public class ThreadPoolWorkManagerTestCase { + + /** + * Wait up to 20 seconds for the Work units to complete + */ + private static final long WAIT_TIMEOUT = 20000; + + /** + * This is the shared instance of the ThreadPoolWorkManager used by the tests + */ + private static ThreadPoolWorkManager workManager = null; + + /** + * Setup the ThreadPoolWorkManager + */ + @BeforeClass + public static void setup() { + workManager = new ThreadPoolWorkManager(10); + } + + /** + * Make sure that the ThreadPoolWorkManager is stopped after running the tests + */ + @AfterClass + public static void destroy() { + if (workManager != null) { + workManager.destroy(); + } + } + + /** + * Tests running a single fast job on the ThreadPoolWorkManager + */ + @Test + public void testSingleFastJob() { + // Create the work and register it + TimeDelayWork fast = new TimeDelayWork(10); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that fails on the ThreadPoolWorkManager + */ + @Test + public void testSingleFailingJob() { + // Create the work and register it + FailingWork fail = new FailingWork(); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fail, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(1, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs on the ThreadPoolWorkManager + */ + @Test + public void testMultipleJobs() { + // Create the work and register it + TimeDelayWork fast1 = new TimeDelayWork(5); + TimeDelayWork fast2 = new TimeDelayWork(10); + TimeDelayWork fast3 = new TimeDelayWork(20); + TimeDelayWork slow1= new TimeDelayWork(200); + TimeDelayWork slow2 = new TimeDelayWork(200); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast1, listener); + workManager.schedule(fast2, listener); + workManager.schedule(fast3, listener); + workManager.schedule(slow1, listener); + workManager.schedule(slow2, listener); + + // Wait for the 5 jobs to complete + waitForWorkToComplete(listener, 5); + + // Test that the job completed successfully. + Assert.assertEquals(5, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(5, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs some of which fail on the + * ThreadPoolWorkManager + */ + @Test + public void testMultipleJobsSomeFail() { + // Create the work and register it + TimeDelayWork fast1 = new TimeDelayWork(5); + TimeDelayWork fast2 = new TimeDelayWork(10); + TimeDelayWork fast3 = new TimeDelayWork(20); + TimeDelayWork slow1= new TimeDelayWork(200); + TimeDelayWork slow2 = new TimeDelayWork(200); + FailingWork fail1 = new FailingWork(); + FailingWork fail2 = new FailingWork(); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast1, listener); + workManager.schedule(fast2, listener); + workManager.schedule(fail1, listener); + workManager.schedule(fast3, listener); + workManager.schedule(slow1, listener); + workManager.schedule(fail2, listener); + workManager.schedule(slow2, listener); + + // Wait for the 7 jobs to complete + waitForWorkToComplete(listener, 7); + + // Test that the job completed successfully. + Assert.assertEquals(7, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(7, listener.getWorkStartedCallCount()); + Assert.assertEquals(7, listener.getWorkCompletedCallCount()); + Assert.assertEquals(2, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that has no listener + */ + @Test + public void testSingleFastJobWithNoListener() { + // Create the work and register it + TimeDelayWork fast = new TimeDelayWork(10); + workManager.schedule(fast); + + // Wait for the job to complete + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = fast.getRunCompletedCount(); + if (completedCount == 1) { + break; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for the job to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + + // Make sure we have got one completed run + Assert.assertEquals(1, fast.getRunCompletedCount()); + } + + /** + * Waits for the specified number of jobs to complete or the timeout to fire. + * + * @param listener The listener to use to track Work unit completion + * @param completedWorkItemsToWaitFor The number of Work items to complete + */ + private void waitForWorkToComplete(TestWorkListener listener, int completedWorkItemsToWaitFor) { + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = listener.getWorkCompletedCallCount(); + if (completedCount == completedWorkItemsToWaitFor) { + return; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for more jobs to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java new file mode 100644 index 0000000000..f6435659ef --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple Work item that will sleep in the run() method for the specified + * period of time + * + * @version $Rev$ $Date$ + */ +public class TimeDelayWork extends Work { + + /** + * Count of completed run() method calls + */ + private AtomicInteger runCompletedCount = new AtomicInteger(); + + /** + * The amount of time to sleep in the Run loop + */ + private final long sleepTime; + + /** + * Constructor + * + * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method + */ + public TimeDelayWork(long sleepTime) { + super(null); + this.sleepTime = sleepTime; + } + + /** + * {@inheritDoc} + */ + public boolean isDaemon() { + return false; + } + + /** + * {@inheritDoc} + */ + public void release() { + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + public void run() { + System.out.println("Starting " + this); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Done " + this); + runCompletedCount.incrementAndGet(); + } + + /** + * Returns the number of completed calls to run() + * + * @return The number of completed calls to run() + */ + public int getRunCompletedCount() { + return runCompletedCount.get(); + } +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java new file mode 100644 index 0000000000..ca7bf9b3d7 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.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.sca.scope; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.junit.Test; +/** + * @version $Rev$ $Date$ + */ +public class ScopeTestCase { + + @Test + public void testEquals() throws Exception { + Scope scope = new Scope("COMPOSITE"); + assertTrue(scope.equals(Scope.COMPOSITE)); + } + + @Test + public void testEqualsNew() throws Exception { + Scope foo = new Scope("foo"); + Scope foo2 = new Scope("FOO"); + assertTrue(foo.equals(foo2)); + } + + @Test + public void testNotEquals() throws Exception { + Scope foo = new Scope("BAR"); + Scope foo2 = new Scope("FOO"); + assertFalse(foo.equals(foo2)); + } + + @Test + public void testNotEqualsDifferent() throws Exception { + Scope foo = new Scope("FOO"); + assertFalse(foo.equals(new Bar("FOO"))); + } + + public class Bar { + String scope; + + public Bar(String scope) { + this.scope = scope; + } + } + + +} diff --git a/tags/java/sca/2.0-M4-RC1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest new file mode 100644 index 0000000000..ad23df3761 --- /dev/null +++ b/tags/java/sca/2.0-M4-RC1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name=implementation.last, stage=implementation, after=* +name=reference.first, stage=reference, before=* +name=reference.transaction, stage=reference, after=reference.interface +name=reference.binding.header, stage=reference.binding, after=reference.binding.transport +name=service.binding.header, stage=service.binding, after=service.binding.transport +name=service.transaction, stage=service, after=service.binding, before=component.service +name=implementation.transaction, stage=implementation, before=implementation.policy -- cgit v1.2.3