From cdc40905ce50878dc894a27f6d30661517e59ad4 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Tue, 9 Sep 2008 02:37:58 +0000 Subject: Creating a branch for the android work. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@693346 13f79535-47bb-0310-9956-ffa450edef68 --- .../sca-android/android-jdk-classes/.classpath | 6 + branches/sca-android/android-jdk-classes/.project | 17 + .../android-jdk-classes/AndroidManifest.xml | 12 + .../src/javax/xml/XMLConstants.java | 196 +++ .../src/javax/xml/namespace/QName.java | 515 +++++++ .../src/javax/xml/transform/Result.java | 70 + .../src/javax/xml/transform/Source.java | 36 + .../src/javax/xml/transform/dom/DOMSource.java | 122 ++ .../src/javax/xml/transform/sax/SAXSource.java | 195 +++ .../tuscany/sca/android/ContextRegistry.java | 55 + .../apache/tuscany/sca/android/DexResource.java | 190 +++ .../tuscany/sca/android/DexURLConnection.java | 128 ++ .../tuscany/sca/android/DexURLStreamHandler.java | 15 + .../sca/android/DexURLStreamHandlerFactory.java | 33 + branches/sca-android/binding-jsonrpc/.classpath | 84 ++ branches/sca-android/binding-jsonrpc/.project | 51 + branches/sca-android/binding-jsonrpc/DISCLAIMER | 8 + branches/sca-android/binding-jsonrpc/LICENSE | 205 +++ branches/sca-android/binding-jsonrpc/NOTICE | 6 + branches/sca-android/binding-jsonrpc/pom.xml | 144 ++ .../sca/binding/jsonrpc/JSONRPCBinding.java | 96 ++ .../sca/binding/jsonrpc/JSONRPCServiceServlet.java | 284 ++++ .../tuscany/sca/binding/jsonrpc/JavaToSmd.java | 56 + .../binding/jsonrpc/ScaDomainScriptServlet.java | 114 ++ .../jsonrpc/provider/JSONRPCBindingInvoker.java | 45 + .../provider/JSONRPCBindingProviderFactory.java | 64 + .../provider/JSONRPCReferenceBindingProvider.java | 70 + .../provider/JSONRPCServiceBindingProvider.java | 189 +++ ...ca.contribution.processor.StAXArtifactProcessor | 19 + ...che.tuscany.sca.provider.BindingProviderFactory | 19 + .../apache/tuscany/sca/binding/jsonrpc/jsonrpc.js | 493 +++++++ .../apache/tuscany/sca/binding/jsonrpc/Echo.java | 29 + .../sca/binding/jsonrpc/EchoComponentImpl.java | 34 + .../binding/jsonrpc/JSONRPCServiceTestCase.java | 67 + .../src/test/resources/JSONRPCBinding.composite | 35 + branches/sca-android/calculator-android/.classpath | 113 ++ branches/sca-android/calculator-android/.project | 33 + .../calculator-android/AndroidManifest.xml | 12 + .../calculator-android/res/drawable/icon.png | Bin 0 -> 6094 bytes .../calculator-android/res/layout/main.xml | 12 + .../res/raw/calculator_composite | 49 + .../sca-android/calculator-android/res/raw/sca.xsd | 22 + .../calculator-android/res/raw/sca_all.xsd | 32 + .../calculator-android/res/raw/sca_binding_ejb.xsd | 43 + .../calculator-android/res/raw/sca_binding_jms.xsd | 135 ++ .../calculator-android/res/raw/sca_binding_sca.xsd | 23 + .../res/raw/sca_binding_webservice.xsd | 26 + .../calculator-android/res/raw/sca_core.xsd | 350 +++++ .../calculator-android/res/raw/sca_definitions.xsd | 25 + .../res/raw/sca_implementation_bpel.xsd | 43 + .../res/raw/sca_implementation_composite_xsd | 23 + .../res/raw/sca_implementation_cpp.xsd | 53 + .../res/raw/sca_implementation_ejb.xsd | 25 + .../res/raw/sca_implementation_java.xsd | 24 + .../res/raw/sca_implementation_spring.xsd | 24 + .../res/raw/sca_interface_cpp.xsd | 40 + .../res/raw/sca_interface_java.xsd | 23 + .../res/raw/sca_interface_wsdl.xsd | 23 + .../calculator-android/res/raw/sca_policy.xsd | 76 ++ .../calculator-android/res/raw/tuscany_sca.xsd | 45 + .../res/raw/tuscany_sca_binding_atom.xsd | 40 + .../res/raw/tuscany_sca_binding_dwr.xsd | 40 + .../res/raw/tuscany_sca_binding_http.xsd | 40 + .../res/raw/tuscany_sca_binding_jsonrpc.xsd | 40 + .../res/raw/tuscany_sca_binding_notification.xsd | 42 + .../res/raw/tuscany_sca_binding_rmi.xsd | 43 + .../res/raw/tuscany_sca_binding_rss.xsd | 40 + .../res/raw/tuscany_sca_implementation_node.xsd | 42 + .../tuscany_sca_implementation_notification.xsd | 42 + .../res/raw/tuscany_sca_implementation_osgi.xsd | 43 + .../raw/tuscany_sca_implementation_resource.xsd | 42 + .../res/raw/tuscany_sca_implementation_script.xsd | 43 + .../res/raw/tuscany_sca_implementation_widget.xsd | 42 + .../res/raw/tuscany_sca_implementation_xquery.xsd | 42 + .../calculator-android/res/values/strings.xml | 4 + .../src/calculator/AddService.java | 28 + .../src/calculator/AddServiceImpl.java | 35 + .../src/calculator/CalculatorService.java | 35 + .../src/calculator/CalculatorServiceImpl.java | 70 + .../src/calculator/DivideService.java | 28 + .../src/calculator/DivideServiceImpl.java | 35 + .../src/calculator/MultiplyService.java | 28 + .../src/calculator/MultiplyServiceImpl.java | 35 + .../src/calculator/SubtractService.java | 28 + .../src/calculator/SubtractServiceImpl.java | 35 + .../src/calculator/android/CalculatorClient.java | 36 + branches/sca-android/contribution-impl/.classpath | 28 + branches/sca-android/contribution-impl/.project | 26 + branches/sca-android/contribution-impl/DISCLAIMER | 8 + branches/sca-android/contribution-impl/LICENSE | 205 +++ branches/sca-android/contribution-impl/NOTICE | 6 + branches/sca-android/contribution-impl/pom.xml | 69 + .../processor/impl/DexContributionProcessor.java | 124 ++ .../impl/FolderContributionProcessor.java | 156 +++ .../processor/impl/JarContributionProcessor.java | 123 ++ .../service/impl/ContributionRepositoryImpl.java | 333 +++++ .../service/impl/ContributionServiceImpl.java | 520 +++++++ .../service/impl/PackageTypeDescriberImpl.java | 119 ++ .../sca/contribution/service/util/FileHelper.java | 701 ++++++++++ .../sca/contribution/service/util/IOHelper.java | 190 +++ ...any.sca.contribution.processor.PackageProcessor | 19 + ...FolderContributionPackageProcessorTestCase.java | 46 + .../JarContributionPackageProcessorTestCase.java | 55 + ...URLartifactProcessorExtensionPointTestCase.java | 111 ++ .../resolver/DefaultModelResolverTestCase.java | 86 ++ .../resolver/ExtensibleModelResolverTestCase.java | 126 ++ .../contribution/resolver/TestModelResolver.java | 58 + .../services/ContributionRepositoryTestCase.java | 81 ++ .../services/PackageTypeDescriberImplTestCase.java | 63 + .../resources/deployables/sample-calculator.jar | Bin 0 -> 26901 bytes .../resources/repository/sample-calculator.jar | Bin 0 -> 29164 bytes .../src/test/resources/test.composite | 22 + .../contribution-impl/src/test/resources/test.ext | 0 branches/sca-android/contribution/.classpath | 16 + branches/sca-android/contribution/.project | 19 + .../.settings/org.eclipse.jdt.core.prefs | 5 + branches/sca-android/contribution/DISCLAIMER | 8 + branches/sca-android/contribution/LICENSE | 205 +++ branches/sca-android/contribution/NOTICE | 6 + branches/sca-android/contribution/pom.xml | 55 + .../apache/tuscany/sca/contribution/Artifact.java | 86 ++ .../tuscany/sca/contribution/ContentType.java | 40 + .../tuscany/sca/contribution/Contribution.java | 116 ++ .../sca/contribution/ContributionFactory.java | 52 + .../contribution/DefaultContributionFactory.java | 32 + .../DefaultModelFactoryExtensionPoint.java | 132 ++ .../tuscany/sca/contribution/DeployedArtifact.java | 29 + .../apache/tuscany/sca/contribution/Export.java | 47 + .../apache/tuscany/sca/contribution/Import.java | 56 + .../contribution/ModelFactoryExtensionPoint.java | 54 + .../tuscany/sca/contribution/PackageType.java | 42 + .../sca/contribution/impl/ArtifactImpl.java | 103 ++ .../contribution/impl/ContributionFactoryImpl.java | 52 + .../sca/contribution/impl/ContributionImpl.java | 154 +++ .../contribution/processor/ArtifactProcessor.java | 48 + .../processor/ArtifactProcessorExtensionPoint.java | 58 + .../processor/BaseStAXArtifactProcessor.java | 512 +++++++ .../DefaultArtifactProcessorExtensionPoint.java | 66 + .../DefaultPackageProcessorExtensionPoint.java | 129 ++ ...DefaultStAXArtifactProcessorExtensionPoint.java | 256 ++++ .../DefaultURLArtifactProcessorExtensionPoint.java | 167 +++ .../DefaultValidatingXMLInputFactory.java | 236 ++++ .../DefaultValidationSchemaExtensionPoint.java | 83 ++ .../processor/ExtensiblePackageProcessor.java | 75 ++ .../processor/ExtensibleStAXArtifactProcessor.java | 185 +++ .../processor/ExtensibleURLArtifactProcessor.java | 122 ++ .../contribution/processor/PackageProcessor.java | 70 + .../processor/PackageProcessorExtensionPoint.java | 50 + .../processor/StAXArtifactProcessor.java | 61 + .../StAXArtifactProcessorExtensionPoint.java | 29 + .../processor/URLArtifactProcessor.java | 51 + .../URLArtifactProcessorExtensionPoint.java | 29 + .../processor/ValidatingXMLStreamReader.java | 336 +++++ .../processor/ValidationSchemaExtensionPoint.java | 52 + .../sca/contribution/resolver/ClassReference.java | 106 ++ .../resolver/DefaultImportAllModelResolver.java | 80 ++ .../resolver/DefaultModelResolver.java | 60 + .../DefaultModelResolverExtensionPoint.java | 114 ++ .../resolver/ExtensibleModelResolver.java | 172 +++ .../sca/contribution/resolver/ModelResolver.java | 69 + .../resolver/ModelResolverExtensionPoint.java | 52 + .../contribution/resolver/ResourceReference.java | 101 ++ .../contribution/scanner/ContributionScanner.java | 66 + .../scanner/ContributionScannerExtensionPoint.java | 50 + .../DefaultContributionScannerExtensionPoint.java | 125 ++ .../service/ContributionException.java | 45 + .../contribution/service/ContributionListener.java | 58 + .../ContributionListenerExtensionPoint.java | 44 + .../service/ContributionReadException.java | 94 ++ .../service/ContributionRepository.java | 128 ++ .../service/ContributionResolveException.java | 41 + .../service/ContributionRuntimeException.java | 44 + .../contribution/service/ContributionService.java | 141 ++ .../service/ContributionWriteException.java | 61 + .../DefaultContributionListenerExtensionPoint.java | 109 ++ .../service/ExtensibleContributionListener.java | 77 ++ .../sca/contribution/service/TypeDescriber.java | 38 + .../service/UnrecognizedElementException.java | 48 + .../service/UnsupportedContentTypeException.java | 42 + .../service/UnsupportedPackageTypeException.java | 39 + ...he.tuscany.sca.contribution.ContributionFactory | 18 + ...any.sca.contribution.ModelFactoryExtensionPoint | 18 + ...ocessor.ContributionPostProcessorExtensionPoint | 18 + ...bution.processor.PackageProcessorExtensionPoint | 18 + ...n.processor.StAXArtifactProcessorExtensionPoint | 18 + ...on.processor.URLArtifactProcessorExtensionPoint | 18 + ...bution.processor.ValidationSchemaExtensionPoint | 18 + ...ntribution.resolver.ModelResolverExtensionPoint | 18 + ...ution.scanner.ContributionScannerExtensionPoint | 18 + ...tion.service.ContributionListenerExtensionPoint | 18 + branches/sca-android/core-android/.classpath | 25 + branches/sca-android/core-android/.project | 23 + branches/sca-android/core-android/DISCLAIMER | 8 + branches/sca-android/core-android/LICENSE | 205 +++ branches/sca-android/core-android/NOTICE | 6 + branches/sca-android/core-android/pom.xml | 82 ++ .../sca/core/assembly/ActivationException.java | 37 + .../sca/core/assembly/CompositeActivator.java | 154 +++ .../sca/core/assembly/CompositeActivatorImpl.java | 967 +++++++++++++ .../sca/core/assembly/EndpointReferenceImpl.java | 186 +++ .../core/assembly/ReferenceParameterProcessor.java | 89 ++ .../sca/core/assembly/ReferenceParametersImpl.java | 139 ++ .../sca/core/assembly/RuntimeAssemblyFactory.java | 53 + .../sca/core/assembly/RuntimeComponentImpl.java | 94 ++ .../assembly/RuntimeComponentReferenceImpl.java | 122 ++ .../core/assembly/RuntimeComponentServiceImpl.java | 153 +++ .../tuscany/sca/core/assembly/RuntimeWireImpl.java | 377 ++++++ .../sca/core/context/CallableReferenceImpl.java | 456 +++++++ .../sca/core/context/ComponentContextHelper.java | 307 +++++ .../sca/core/context/ComponentContextImpl.java | 397 ++++++ .../context/DefaultComponentContextFactory.java | 70 + .../tuscany/sca/core/context/InstanceWrapper.java | 48 + .../sca/core/context/RequestContextImpl.java | 105 ++ .../sca/core/context/ServiceReferenceImpl.java | 132 ++ .../core/conversation/ConversationListener.java | 40 + .../sca/core/conversation/ConversationManager.java | 71 + .../core/conversation/ConversationManagerImpl.java | 204 +++ .../sca/core/conversation/ConversationState.java | 29 + .../core/conversation/ExtendedConversation.java | 66 + .../conversation/ExtendedConversationImpl.java | 269 ++++ .../tuscany/sca/core/event/BaseEventPublisher.java | 89 ++ .../tuscany/sca/core/event/ComponentStart.java | 54 + .../tuscany/sca/core/event/ComponentStop.java | 53 + .../tuscany/sca/core/event/ConversationEnd.java | 53 + .../tuscany/sca/core/event/ConversationStart.java | 52 + .../tuscany/sca/core/event/HttpSessionEnd.java | 53 + .../tuscany/sca/core/event/HttpSessionStart.java | 52 + .../apache/tuscany/sca/core/event/RequestEnd.java | 45 + .../tuscany/sca/core/event/RequestStart.java | 45 + .../sca/core/factory/ObjectCreationException.java | 47 + .../tuscany/sca/core/factory/ObjectFactory.java | 35 + .../invocation/CallableReferenceObjectFactory.java | 63 + .../invocation/CallbackInterfaceInterceptor.java | 57 + .../sca/core/invocation/CallbackReferenceImpl.java | 187 +++ .../invocation/CallbackReferenceObjectFactory.java | 48 + .../core/invocation/CallbackWireObjectFactory.java | 47 + .../sca/core/invocation/CglibProxyFactory.java | 155 +++ .../DefaultProxyFactoryExtensionPoint.java | 152 +++ .../core/invocation/ExtensibleWireProcessor.java | 44 + .../sca/core/invocation/InvocationChainImpl.java | 189 +++ .../invocation/JDKCallbackInvocationHandler.java | 110 ++ .../sca/core/invocation/JDKInvocationHandler.java | 489 +++++++ .../sca/core/invocation/JDKProxyFactory.java | 102 ++ .../sca/core/invocation/MessageFactoryImpl.java | 36 + .../tuscany/sca/core/invocation/MessageImpl.java | 104 ++ .../invocation/NoMethodForOperationException.java | 43 + .../core/invocation/NonBlockingInterceptor.java | 163 +++ .../tuscany/sca/core/invocation/PhaseManager.java | 247 ++++ .../tuscany/sca/core/invocation/PhaseSorter.java | 234 ++++ .../core/invocation/ProxyCreationException.java | 48 + .../tuscany/sca/core/invocation/ProxyFactory.java | 87 ++ .../invocation/ProxyFactoryExtensionPoint.java | 58 + .../sca/core/invocation/RuntimeWireInvoker.java | 245 ++++ .../core/invocation/TargetInvocationException.java | 45 + .../sca/core/invocation/ThreadMessageContext.java | 72 + .../sca/core/invocation/WireObjectFactory.java | 54 + .../sca/core/scope/AbstractScopeContainer.java | 201 +++ .../sca/core/scope/CompositeScopeContainer.java | 77 ++ .../core/scope/CompositeScopeContainerFactory.java | 37 + .../core/scope/ConversationalScopeContainer.java | 290 ++++ .../scope/ConversationalScopeContainerFactory.java | 44 + .../sca/core/scope/HttpSessionScopeContainer.java | 83 ++ .../scope/HttpSessionScopeContainerFactory.java | 41 + .../sca/core/scope/RequestScopeContainer.java | 86 ++ .../core/scope/RequestScopeContainerFactory.java | 37 + .../org/apache/tuscany/sca/core/scope/Scope.java | 66 + .../tuscany/sca/core/scope/ScopeContainer.java | 159 +++ .../sca/core/scope/ScopeContainerFactory.java | 32 + .../tuscany/sca/core/scope/ScopeRegistry.java | 43 + .../tuscany/sca/core/scope/ScopeRegistryImpl.java | 62 + .../core/scope/ScopedImplementationProvider.java | 65 + .../sca/core/scope/ScopedRuntimeComponent.java | 40 + .../sca/core/scope/StatelessScopeContainer.java | 55 + .../core/scope/StatelessScopeContainerFactory.java | 37 + .../sca/core/scope/TargetDestructionException.java | 44 + .../core/scope/TargetInitializationException.java | 44 + .../sca/core/scope/TargetNotFoundException.java | 44 + .../sca/core/scope/TargetResolutionException.java | 44 + .../apache/tuscany/sca/core/store/MemoryStore.java | 195 +++ .../apache/tuscany/sca/core/work/Jsr237Work.java | 63 + .../tuscany/sca/core/work/Jsr237WorkScheduler.java | 182 +++ .../sca/core/work/ThreadPoolWorkManager.java | 228 ++++ .../tuscany/sca/core/work/WorkEventImpl.java | 74 + .../apache/tuscany/sca/core/work/WorkItemImpl.java | 168 +++ .../org.apache.tuscany.sca.work.WorkScheduler | 18 + .../DefaultExtensionPointRegistryTestCase.java | 52 + .../sca/core/event/BaseEventPublisherTestCase.java | 98 ++ .../tuscany/sca/core/event/EventTestCase.java | 69 + .../sca/core/invocation/PhaseManagerTestCase.java | 51 + .../sca/core/invocation/PhaseSorterTestCase.java | 63 + .../core/scope/AbstractScopeContainerTestCase.java | 69 + .../sca/core/store/MemoryStoreTestCase.java | 165 +++ .../wire/CallbackInterfaceInterceptorTestCase.java | 62 + .../sca/core/wire/InvocationChainImplTestCase.java | 93 ++ .../core/wire/NonBlockingInterceptorTestCase.java | 73 + .../apache/tuscany/sca/scope/ScopeTestCase.java | 61 + .../org.apache.tuscany.sca.invocation.PhaseTest | 5 + branches/sca-android/core-databinding/.classpath | 41 + branches/sca-android/core-databinding/.project | 31 + branches/sca-android/core-databinding/DISCLAIMER | 8 + branches/sca-android/core-databinding/LICENSE | 205 +++ branches/sca-android/core-databinding/NOTICE | 6 + branches/sca-android/core-databinding/pom.xml | 76 ++ .../module/DataBindingModuleActivator.java | 93 ++ .../DataBindingJavaInterfaceProcessor.java | 191 +++ .../transformers/Array2ArrayTransformer.java | 108 ++ .../Exception2ExceptionTransformer.java | 112 ++ .../transformers/Input2InputTransformer.java | 213 +++ .../transformers/Output2OutputTransformer.java | 203 +++ .../wire/DataBindingRuntimeWireProcessor.java | 186 +++ .../wire/DataTransformationInterceptor.java | 263 ++++ .../databinding/wire/PassByValueInterceptor.java | 247 ++++ .../org.apache.tuscany.sca.core.ModuleActivator | 18 + .../DataBindingJavaInterfaceProcessorTestCase.java | 88 ++ .../transformers/IDLTransformerTestCase.java.fixme | 229 ++++ branches/sca-android/extensibility/.classpath | 10 + branches/sca-android/extensibility/.project | 13 + .../.settings/org.eclipse.jdt.core.prefs | 5 + branches/sca-android/extensibility/DISCLAIMER | 8 + branches/sca-android/extensibility/LICENSE | 205 +++ branches/sca-android/extensibility/NOTICE | 5 + branches/sca-android/extensibility/pom.xml | 31 + .../sca/extensibility/ServiceDeclaration.java | 134 ++ .../sca/extensibility/ServiceDiscovery.java | 436 ++++++ branches/sca-android/host-android/.classpath | 62 + branches/sca-android/host-android/.project | 44 + branches/sca-android/host-android/DISCLAIMER | 8 + branches/sca-android/host-android/LICENSE | 205 +++ branches/sca-android/host-android/NOTICE | 6 + branches/sca-android/host-android/pom.xml | 106 ++ .../tuscany/sca/host/embedded/SCADomain.java | 338 +++++ .../tuscany/sca/host/embedded/SCADomainBean.java | 120 ++ .../sca/host/embedded/SCATestCaseRunner.java | 216 +++ .../host/embedded/impl/ComponentManagerImpl.java | 115 ++ .../sca/host/embedded/impl/DefaultSCADomain.java | 584 ++++++++ .../sca/host/embedded/impl/EmbeddedSCADomain.java | 234 ++++ .../host/embedded/impl/HotUpdatableSCADomain.java | 387 ++++++ .../sca/host/embedded/impl/ReallySmallRuntime.java | 407 ++++++ .../embedded/impl/ReallySmallRuntimeBuilder.java | 297 ++++ .../embedded/management/ComponentListener.java | 29 + .../host/embedded/management/ComponentManager.java | 43 + .../sca/host/embedded/SCADomainBeanTestCase.java | 57 + .../sca/host/embedded/SCADomainTestCase.java | 56 + .../embedded/impl/DefaultSCADomainTestCase.java | 63 + .../embedded/impl/EmbeddedSCADomainTestCase.java | 189 +++ .../sca/host/embedded/impl/TestModelResolver.java | 104 ++ .../DefaultTestImplementationFactory.java | 47 + .../test/extension/TestImplementation.java | 45 + .../test/extension/TestImplementationFactory.java | 37 + .../host/embedded/test/extension/TestService.java | 30 + .../extension/impl/TestImplementationImpl.java | 118 ++ .../impl/TestImplementationProcessor.java | 96 ++ .../test/extension/module/TestModuleActivator.java | 66 + .../provider/TestImplementationProvider.java | 65 + .../TestImplementationProviderFactory.java | 48 + .../test/extension/provider/TestInvoker.java | 52 + .../org.apache.tuscany.sca.core.ModuleActivator | 18 + .../host-android/src/test/resources/test.composite | 30 + .../host-android/src/test/resources/test.txt | 16 + .../sca-android/interface-java-jaxws/.classpath | 42 + branches/sca-android/interface-java-jaxws/.project | 30 + .../sca-android/interface-java-jaxws/DISCLAIMER | 8 + branches/sca-android/interface-java-jaxws/LICENSE | 205 +++ branches/sca-android/interface-java-jaxws/NOTICE | 6 + branches/sca-android/interface-java-jaxws/pom.xml | 188 +++ .../java/jaxws/JAXWSFaultExceptionMapper.java | 253 ++++ .../java/jaxws/JAXWSJavaInterfaceProcessor.java | 232 ++++ .../tuscany/sca/interfacedef/java/jaxws/Bean.java | 23 + .../tuscany/sca/interfacedef/java/jaxws/Bean1.java | 36 + .../tuscany/sca/interfacedef/java/jaxws/Bean2.java | 36 + .../jaxws/JAXWSJavaInterfaceProcessorTestCase.java | 98 ++ .../sca/interfacedef/java/jaxws/MyException.java | 49 + .../sca/interfacedef/java/jaxws/MyServiceImpl.java | 52 + .../test/resources/wsdl/StockExceptionTest.wsdl | 148 ++ branches/sca-android/interface-java/.classpath | 18 + branches/sca-android/interface-java/.project | 21 + branches/sca-android/interface-java/DISCLAIMER | 8 + branches/sca-android/interface-java/LICENSE | 205 +++ branches/sca-android/interface-java/NOTICE | 6 + branches/sca-android/interface-java/pom.xml | 63 + .../java/DefaultJavaInterfaceFactory.java | 97 ++ .../sca/interfacedef/java/JavaInterface.java | 72 + .../interfacedef/java/JavaInterfaceContract.java | 32 + .../interfacedef/java/JavaInterfaceFactory.java | 82 ++ .../sca/interfacedef/java/JavaOperation.java | 45 + .../java/impl/JavaInterfaceContractImpl.java | 39 + .../java/impl/JavaInterfaceFactoryImpl.java | 71 + .../interfacedef/java/impl/JavaInterfaceImpl.java | 101 ++ .../java/impl/JavaInterfaceIntrospectorImpl.java | 225 ++++ .../interfacedef/java/impl/JavaInterfaceUtil.java | 151 +++ .../interfacedef/java/impl/JavaOperationImpl.java | 73 + .../java/impl/PolicyJavaInterfaceVisitor.java | 159 +++ .../java/introspect/JavaInterfaceVisitor.java | 39 + ...cany.sca.interfacedef.java.JavaInterfaceFactory | 18 + .../java/impl/JavaInterfaceUtilTestCase.java | 121 ++ .../impl/ConversationalIntrospectionTestCase.java | 98 ++ ...JavaInterfaceProcessorRegistryImplTestCase.java | 107 ++ .../impl/PolicyProcessorTestCase.java | 108 ++ branches/sca-android/retrotranslator_readme | 85 ++ .../sca-android/tuscany-assembly-xml/.classpath | 40 + branches/sca-android/tuscany-assembly-xml/.project | 30 + .../.settings/org.eclipse.jdt.core.prefs | 5 + .../sca-android/tuscany-assembly-xml/DISCLAIMER | 8 + branches/sca-android/tuscany-assembly-xml/LICENSE | 205 +++ branches/sca-android/tuscany-assembly-xml/NOTICE | 6 + branches/sca-android/tuscany-assembly-xml/pom.xml | 116 ++ .../sca/assembly/xml/BaseAssemblyProcessor.java | 814 +++++++++++ .../xml/ComponentTypeDocumentProcessor.java | 122 ++ .../assembly/xml/ComponentTypeModelResolver.java | 95 ++ .../sca/assembly/xml/ComponentTypeProcessor.java | 355 +++++ .../assembly/xml/CompositeDocumentProcessor.java | 174 +++ .../sca/assembly/xml/CompositeModelResolver.java | 83 ++ .../sca/assembly/xml/CompositeProcessor.java | 989 ++++++++++++++ .../assembly/xml/ConfiguredOperationProcessor.java | 104 ++ .../apache/tuscany/sca/assembly/xml/Constants.java | 95 ++ .../xml/ConstrainingTypeDocumentProcessor.java | 121 ++ .../xml/ConstrainingTypeModelResolver.java | 83 ++ .../assembly/xml/ConstrainingTypeProcessor.java | 257 ++++ .../assembly/xml/DefaultBeanModelProcessor.java | 246 ++++ .../assembly/xml/PolicyAttachPointProcessor.java | 263 ++++ ...tuscany.sca.contribution.resolver.ModelResolver | 20 + .../sca/assembly/xml/BuildPolicyTestCase.java | 166 +++ .../sca/assembly/xml/MockPolicyProcessor.java | 68 + .../tuscany/sca/assembly/xml/ReadAllTestCase.java | 162 +++ .../sca/assembly/xml/ReadDocumentTestCase.java | 223 +++ .../tuscany/sca/assembly/xml/ReadTestCase.java | 99 ++ .../sca/assembly/xml/ResolvePolicyTestCase.java | 198 +++ .../tuscany/sca/assembly/xml/ResolveTestCase.java | 111 ++ .../sca/assembly/xml/TestModelResolver.java | 63 + .../assembly/xml/TestSCABindingFactoryImpl.java | 35 + .../sca/assembly/xml/TestSCABindingImpl.java | 213 +++ .../tuscany/sca/assembly/xml/WireTestCase.java | 146 ++ .../tuscany/sca/assembly/xml/WriteAllTestCase.java | 148 ++ .../tuscany/sca/assembly/xml/Calculator.composite | 53 + .../xml/CalculatorComponent.constrainingType | 34 + .../sca/assembly/xml/CalculatorImpl.componentType | 31 + .../sca/assembly/xml/JavaScriptReference.composite | 37 + .../sca/assembly/xml/RMIBindingTest.composite | 43 + .../sca/assembly/xml/TestAllCalculator.composite | 128 ++ .../sca/assembly/xml/TestAllDivide.composite | 56 + .../assembly/xml/TestAllPolicyCalculator.composite | 129 ++ .../sca/assembly/xml/another_test_definitions.xml | 97 ++ .../tuscany/sca/assembly/xml/test_definitions.xml | 175 +++ branches/sca-android/tuscany-assembly/.classpath | 13 + branches/sca-android/tuscany-assembly/.project | 18 + .../.settings/org.eclipse.jdt.core.prefs | 5 + branches/sca-android/tuscany-assembly/DISCLAIMER | 8 + branches/sca-android/tuscany-assembly/LICENSE | 205 +++ branches/sca-android/tuscany-assembly/NOTICE | 6 + branches/sca-android/tuscany-assembly/pom.xml | 50 + .../tuscany/sca/assembly/AbstractContract.java | 77 ++ .../tuscany/sca/assembly/AbstractProperty.java | 122 ++ .../tuscany/sca/assembly/AbstractReference.java | 43 + .../tuscany/sca/assembly/AbstractService.java | 28 + .../tuscany/sca/assembly/AssemblyFactory.java | 155 +++ .../java/org/apache/tuscany/sca/assembly/Base.java | 43 + .../org/apache/tuscany/sca/assembly/Binding.java | 63 + .../org/apache/tuscany/sca/assembly/Callback.java | 40 + .../org/apache/tuscany/sca/assembly/Component.java | 132 ++ .../tuscany/sca/assembly/ComponentProperty.java | 88 ++ .../tuscany/sca/assembly/ComponentReference.java | 74 + .../tuscany/sca/assembly/ComponentService.java | 59 + .../apache/tuscany/sca/assembly/ComponentType.java | 77 ++ .../org/apache/tuscany/sca/assembly/Composite.java | 110 ++ .../tuscany/sca/assembly/CompositeReference.java | 37 + .../tuscany/sca/assembly/CompositeService.java | 56 + .../tuscany/sca/assembly/ConfiguredOperation.java | 59 + .../tuscany/sca/assembly/ConstrainingType.java | 72 + .../org/apache/tuscany/sca/assembly/Contract.java | 81 ++ .../sca/assembly/DefaultAssemblyFactory.java | 31 + .../apache/tuscany/sca/assembly/Extensible.java | 37 + .../tuscany/sca/assembly/Implementation.java | 27 + .../apache/tuscany/sca/assembly/Multiplicity.java | 49 + .../sca/assembly/OperationsConfigurator.java | 33 + .../tuscany/sca/assembly/OptimizableBinding.java | 66 + .../org/apache/tuscany/sca/assembly/Property.java | 41 + .../org/apache/tuscany/sca/assembly/Reference.java | 56 + .../apache/tuscany/sca/assembly/SCABinding.java | 27 + .../tuscany/sca/assembly/SCABindingFactory.java | 36 + .../org/apache/tuscany/sca/assembly/Service.java | 29 + .../java/org/apache/tuscany/sca/assembly/Wire.java | 67 + .../assembly/builder/ComponentPreProcessor.java | 28 + .../sca/assembly/builder/CompositeBuilder.java | 40 + .../builder/CompositeBuilderException.java | 45 + .../assembly/builder/CompositeBuilderMonitor.java | 36 + .../sca/assembly/builder/DomainBuilder.java | 80 ++ .../tuscany/sca/assembly/builder/Problem.java | 45 + .../builder/impl/BindingPolicyComputer.java | 262 ++++ .../sca/assembly/builder/impl/BindingUtil.java | 142 ++ .../builder/impl/CompositeBuilderImpl.java | 121 ++ .../builder/impl/CompositeCloneBuilderImpl.java | 107 ++ .../impl/CompositeConfigurationBuilderImpl.java | 1417 ++++++++++++++++++++ .../builder/impl/CompositeIncludeBuilderImpl.java | 93 ++ .../builder/impl/CompositeWireBuilderImpl.java | 998 ++++++++++++++ .../builder/impl/DomainWireBuilderImpl.java | 289 ++++ .../builder/impl/ImplementationPolicyComputer.java | 134 ++ .../builder/impl/PolicyComputationException.java | 36 + .../sca/assembly/builder/impl/PolicyComputer.java | 372 +++++ .../sca/assembly/builder/impl/PrintUtil.java | 273 ++++ .../sca/assembly/builder/impl/ProblemImpl.java | 112 ++ .../sca/assembly/builder/impl/PropertyUtil.java | 208 +++ .../sca/assembly/builder/impl/ReferenceUtil.java | 94 ++ .../sca/assembly/impl/AbstractPropertyImpl.java | 114 ++ .../sca/assembly/impl/AbstractReferenceImpl.java | 46 + .../sca/assembly/impl/AbstractServiceImpl.java | 36 + .../sca/assembly/impl/AssemblyFactoryImpl.java | 121 ++ .../apache/tuscany/sca/assembly/impl/BaseImpl.java | 45 + .../tuscany/sca/assembly/impl/CallbackImpl.java | 82 ++ .../tuscany/sca/assembly/impl/ComponentImpl.java | 174 +++ .../sca/assembly/impl/ComponentPropertyImpl.java | 93 ++ .../sca/assembly/impl/ComponentReferenceImpl.java | 86 ++ .../sca/assembly/impl/ComponentServiceImpl.java | 71 + .../sca/assembly/impl/ComponentTypeImpl.java | 115 ++ .../tuscany/sca/assembly/impl/CompositeImpl.java | 143 ++ .../sca/assembly/impl/CompositeReferenceImpl.java | 51 + .../sca/assembly/impl/CompositeServiceImpl.java | 62 + .../sca/assembly/impl/ConfiguredOperationImpl.java | 91 ++ .../sca/assembly/impl/ConstrainingTypeImpl.java | 105 ++ .../tuscany/sca/assembly/impl/ContractImpl.java | 91 ++ .../tuscany/sca/assembly/impl/ExtensibleImpl.java | 44 + .../sca/assembly/impl/ImplementationImpl.java | 74 + .../tuscany/sca/assembly/impl/PropertyImpl.java | 59 + .../tuscany/sca/assembly/impl/ReferenceImpl.java | 116 ++ .../tuscany/sca/assembly/impl/ServiceImpl.java | 99 ++ .../apache/tuscany/sca/assembly/impl/WireImpl.java | 96 ++ ...org.apache.tuscany.sca.assembly.AssemblyFactory | 18 + .../sca/assembly/AssemblyFactoryTestCase.java | 214 +++ .../apache/tuscany/sca/assembly/TestBinding.java | 55 + .../tuscany/sca/assembly/TestImplementation.java | 61 + .../apache/tuscany/sca/assembly/TestInterface.java | 42 + .../sca/assembly/TestInterfaceContract.java | 41 + .../apache/tuscany/sca/assembly/TestOperation.java | 30 + .../builder/impl/CalculateBindingURITestCase.java | 554 ++++++++ .../builder/impl/CompositeBuilderTestCase.java | 128 ++ .../assembly/builder/impl/PrintUtilTestCase.java | 229 ++++ branches/sca-android/tuscany-core-spi/.classpath | 21 + branches/sca-android/tuscany-core-spi/.project | 21 + .../.settings/org.eclipse.jdt.core.prefs | 5 + branches/sca-android/tuscany-core-spi/DISCLAIMER | 8 + branches/sca-android/tuscany-core-spi/LICENSE | 205 +++ branches/sca-android/tuscany-core-spi/NOTICE | 6 + branches/sca-android/tuscany-core-spi/pom.xml | 91 ++ .../tuscany-core-spi/src/doc/Context Model.emx | 673 ++++++++++ .../sca/context/ComponentContextFactory.java | 38 + .../sca/context/ContextFactoryExtensionPoint.java | 50 + .../DefaultContextFactoryExtensionPoint.java | 67 + .../tuscany/sca/context/PropertyValueFactory.java | 38 + .../tuscany/sca/context/RequestContextFactory.java | 33 + .../sca/core/DefaultExtensionPointRegistry.java | 171 +++ .../tuscany/sca/core/ExtensionPointRegistry.java | 50 + .../apache/tuscany/sca/core/ModuleActivator.java | 60 + .../java/org/apache/tuscany/sca/event/Event.java | 33 + .../org/apache/tuscany/sca/event/EventFilter.java | 35 + .../apache/tuscany/sca/event/EventPublisher.java | 55 + .../tuscany/sca/event/RuntimeEventListener.java | 35 + .../org/apache/tuscany/sca/event/TrueFilter.java | 37 + .../sca/invocation/DataExchangeSemantics.java | 34 + .../apache/tuscany/sca/invocation/Interceptor.java | 40 + .../tuscany/sca/invocation/InvocationChain.java | 112 ++ .../org/apache/tuscany/sca/invocation/Invoker.java | 36 + .../org/apache/tuscany/sca/invocation/Message.java | 117 ++ .../tuscany/sca/invocation/MessageFactory.java | 36 + .../org/apache/tuscany/sca/invocation/Phase.java | 59 + .../tuscany/sca/management/ManagementService.java | 39 + .../sca/provider/BindingProviderFactory.java | 60 + .../DefaultProviderFactoryExtensionPoint.java | 370 +++++ ...efaultSCADefinitionsProviderExtensionPoint.java | 89 ++ .../sca/provider/ImplementationProvider.java | 68 + .../provider/ImplementationProviderFactory.java | 42 + .../tuscany/sca/provider/PolicyImplementor.java | 38 + .../tuscany/sca/provider/PolicyProvider.java | 41 + .../sca/provider/PolicyProviderFactory.java | 63 + .../tuscany/sca/provider/ProviderFactory.java | 36 + .../provider/ProviderFactoryExtensionPoint.java | 63 + .../sca/provider/ReferenceBindingProvider.java | 76 ++ .../sca/provider/SCADefinitionsProvider.java | 31 + .../provider/SCADefinitionsProviderException.java | 30 + .../SCADefinitionsProviderExtensionPoint.java | 33 + .../sca/provider/ServiceBindingProvider.java | 63 + .../DefaultWireProcessorExtensionPoint.java | 63 + .../tuscany/sca/runtime/EndpointReference.java | 93 ++ .../tuscany/sca/runtime/ReferenceParameters.java | 69 + .../tuscany/sca/runtime/RuntimeComponent.java | 83 ++ .../sca/runtime/RuntimeComponentContext.java | 104 ++ .../sca/runtime/RuntimeComponentReference.java | 99 ++ .../sca/runtime/RuntimeComponentService.java | 138 ++ .../apache/tuscany/sca/runtime/RuntimeWire.java | 101 ++ .../tuscany/sca/runtime/RuntimeWireProcessor.java | 35 + .../RuntimeWireProcessorExtensionPoint.java | 53 + .../sca/store/DuplicateRecordException.java | 45 + .../apache/tuscany/sca/store/RecoveryListener.java | 46 + .../java/org/apache/tuscany/sca/store/Store.java | 96 ++ .../apache/tuscany/sca/store/StoreException.java | 46 + .../tuscany/sca/store/StoreExpirationEvent.java | 71 + .../org/apache/tuscany/sca/store/StoreMonitor.java | 71 + .../tuscany/sca/store/StoreReadException.java | 45 + .../tuscany/sca/store/StoreWriteException.java | 45 + .../tuscany/sca/work/NotificationListener.java | 66 + .../org/apache/tuscany/sca/work/WorkScheduler.java | 57 + .../tuscany/sca/work/WorkSchedulerException.java | 47 + ...cany.sca.provider.ProviderFactoryExtensionPoint | 18 + ...a.provider.SCADefinitionsProviderExtensionPoint | 19 + ....sca.runtime.RuntimeWireProcessorExtensionPoint | 18 + .../tuscany-implementation-java-runtime/.classpath | 32 + .../tuscany-implementation-java-runtime/.project | 31 + .../.settings/org.eclipse.jdt.core.prefs | 5 + .../tuscany-implementation-java-runtime/DISCLAIMER | 8 + .../tuscany-implementation-java-runtime/LICENSE | 205 +++ .../tuscany-implementation-java-runtime/NOTICE | 6 + .../tuscany-implementation-java-runtime/pom.xml | 56 + .../java/context/InstanceFactory.java | 43 + .../java/context/InstanceFactoryProvider.java | 49 + .../java/context/ReflectiveInstanceFactory.java | 86 ++ .../java/context/ReflectiveInstanceWrapper.java | 56 + .../injection/ArrayMultiplicityObjectFactory.java | 54 + .../java/injection/ContextInjector.java | 32 + .../injection/ConversationIDObjectFactory.java | 33 + .../java/injection/FieldInjector.java | 57 + .../java/injection/InjectionRuntimeException.java | 45 + .../implementation/java/injection/Injector.java | 35 + .../java/injection/InvalidAccessorException.java | 43 + .../injection/JavaPropertyValueObjectFactory.java | 293 ++++ .../injection/ListMultiplicityObjectFactory.java | 50 + .../java/injection/MethodInjector.java | 64 + .../injection/RequestContextObjectFactory.java | 55 + .../java/injection/ResourceHost.java | 46 + .../java/injection/ResourceNotFoundException.java | 51 + .../java/injection/ResourceObjectFactory.java | 87 ++ .../injection/ResourceResolutionException.java | 43 + .../java/invocation/EventInvocationException.java | 47 + .../java/invocation/EventInvoker.java | 34 + .../InvalidConversationSequenceException.java | 46 + .../JavaCallbackRuntimeWireProcessor.java | 106 ++ .../invocation/JavaComponentContextFactory.java | 40 + .../invocation/JavaComponentContextProvider.java | 379 ++++++ .../java/invocation/JavaComponentNameFactory.java | 40 + .../java/invocation/JavaImplementationInvoker.java | 133 ++ .../invocation/JavaImplementationProvider.java | 183 +++ .../JavaImplementationProviderFactory.java | 77 ++ .../invocation/JavaInstanceFactoryProvider.java | 183 +++ .../JavaPolicyHandlingRuntimeWireProcessor.java | 124 ++ .../java/invocation/MethodEventInvoker.java | 56 + .../NoConversationalContractException.java | 34 + .../java/invocation/PolicyHandlingInterceptor.java | 72 + .../java/module/JavaRuntimeModuleActivator.java | 215 +++ .../org.apache.tuscany.sca.core.ModuleActivator | 18 + .../java/context/MultiplicityTestCase.java | 34 + .../context/ReflectiveInstanceWrapperTestCase.java | 84 ++ .../CallbackWireObjectFactoryTestCase.java | 54 + .../java/injection/FieldInjectorTestCase.java | 49 + .../java/injection/MethodEventInvokerTestCase.java | 76 ++ .../java/injection/MethodInjectorTestCase.java | 80 ++ .../RequestContextObjectFactoryTestCase.java | 33 + .../injection/ResourceObjectFactoryTestCase.java | 89 ++ .../java/injection/SingletonObjectFactory.java | 39 + .../injection/SingletonObjectFactoryTestCase.java | 33 + .../java/injection/TestObjectFactory.java | 120 ++ .../java/injection/TestObjectFactoryTestCase.java | 77 ++ .../sca/implementation/java/util/Bean1.java | 46 + .../sca/implementation/java/util/Bean2.java | 47 + .../sca/implementation/java/util/Entry.java | 32 + .../java/util/JavaIntrospectionHelperTestCase.java | 181 +++ .../sca/implementation/java/util/SuperBean.java | 48 + .../tuscany-implementation-java-xml/.classpath | 51 + .../tuscany-implementation-java-xml/.project | 39 + .../.settings/org.eclipse.jdt.core.prefs | 5 + .../tuscany-implementation-java-xml/DISCLAIMER | 8 + .../tuscany-implementation-java-xml/LICENSE | 205 +++ .../tuscany-implementation-java-xml/NOTICE | 6 + .../tuscany-implementation-java-xml/pom.xml | 79 ++ .../java/xml/JavaImplementationConstants.java | 31 + .../java/xml/JavaImplementationProcessor.java | 280 ++++ ...ca.contribution.processor.StAXArtifactProcessor | 19 + .../src/test/java/calculator/AddService.java | 25 + .../src/test/java/calculator/AddServiceImpl.java | 35 + .../test/java/calculator/CalculatorService.java | 34 + .../java/calculator/CalculatorServiceImpl.java | 71 + .../src/test/java/calculator/DivideService.java | 25 + .../test/java/calculator/DivideServiceImpl.java | 33 + .../src/test/java/calculator/MultiplyService.java | 25 + .../test/java/calculator/MultiplyServiceImpl.java | 33 + .../src/test/java/calculator/SubtractService.java | 25 + .../test/java/calculator/SubtractServiceImpl.java | 33 + .../sca/implementation/java/xml/ReadTestCase.java | 261 ++++ .../implementation/java/xml/TestModelResolver.java | 88 ++ .../sca/implementation/java/xml/WriteTestCase.java | 86 ++ .../implementation/java/xml/Calculator.composite | 66 + .../sca/implementation/java/xml/definitions.xml | 100 ++ .../java/xml/definitions_with_policysets.xml | 133 ++ .../tuscany-implementation-java/.classpath | 19 + .../tuscany-implementation-java/.project | 22 + .../.settings/org.eclipse.jdt.core.prefs | 5 + .../tuscany-implementation-java/DISCLAIMER | 8 + .../tuscany-implementation-java/LICENSE | 205 +++ .../sca-android/tuscany-implementation-java/NOTICE | 6 + .../tuscany-implementation-java/pom.xml | 50 + .../java/BaseJavaImplementation.java | 59 + .../java/DefaultJavaImplementationFactory.java | 31 + .../java/IntrospectionException.java | 60 + .../implementation/java/JavaImplementation.java | 197 +++ .../java/JavaImplementationFactory.java | 75 ++ .../java/impl/BaseJavaImplementationImpl.java | 84 ++ .../java/impl/JavaClassIntrospectorImpl.java | 128 ++ .../java/impl/JavaConstructorImpl.java | 53 + .../implementation/java/impl/JavaElementImpl.java | 224 ++++ .../java/impl/JavaImplementationFactoryImpl.java | 68 + .../java/impl/JavaImplementationImpl.java | 167 +++ .../java/impl/JavaParameterImpl.java | 35 + .../implementation/java/impl/JavaResourceImpl.java | 85 ++ .../implementation/java/impl/JavaScopeImpl.java | 66 + .../java/introspect/JavaClassVisitor.java | 126 ++ .../introspect/impl/AbstractPropertyProcessor.java | 192 +++ .../impl/AllowsPassByReferenceProcessor.java | 51 + .../impl/AmbiguousConstructorException.java | 40 + .../java/introspect/impl/BaseJavaClassVisitor.java | 64 + .../introspect/impl/ComponentNameProcessor.java | 80 ++ .../java/introspect/impl/ConstructorProcessor.java | 83 ++ .../java/introspect/impl/ContextProcessor.java | 82 ++ .../introspect/impl/ConversationIDProcessor.java | 68 + .../introspect/impl/ConversationProcessor.java | 133 ++ .../java/introspect/impl/DestroyProcessor.java | 58 + .../impl/DuplicateConstructorException.java | 41 + .../impl/DuplicateDestructorException.java | 35 + .../introspect/impl/DuplicateInitException.java | 35 + .../impl/DuplicatePropertyException.java | 34 + .../impl/DuplicateReferenceException.java | 35 + .../impl/DuplicateResourceException.java | 36 + .../java/introspect/impl/EagerInitProcessor.java | 57 + .../introspect/impl/HeuristicPojoProcessor.java | 605 +++++++++ .../impl/IllegalCallbackReferenceException.java | 40 + .../introspect/impl/IllegalContextException.java | 40 + .../impl/IllegalDestructorException.java | 40 + .../java/introspect/impl/IllegalInitException.java | 40 + .../introspect/impl/IllegalPropertyException.java | 40 + .../introspect/impl/IllegalReferenceException.java | 40 + .../introspect/impl/IllegalResourceException.java | 40 + .../impl/IllegalServiceDefinitionException.java | 35 + .../java/introspect/impl/InitProcessor.java | 58 + .../impl/InvalidConstructorException.java | 36 + .../impl/InvalidConversationalImplementation.java | 39 + .../introspect/impl/InvalidPropertyException.java | 35 + .../introspect/impl/InvalidReferenceException.java | 42 + .../introspect/impl/InvalidResourceException.java | 40 + .../java/introspect/impl/InvalidServiceType.java | 48 + .../introspect/impl/JavaIntrospectionHelper.java | 555 ++++++++ .../introspect/impl/NoConstructorException.java | 37 + .../java/introspect/impl/PolicyProcessor.java | 292 ++++ .../java/introspect/impl/PropertyProcessor.java | 46 + .../java/introspect/impl/ReferenceProcessor.java | 208 +++ .../java/introspect/impl/Resource.java | 49 + .../java/introspect/impl/ResourceProcessor.java | 137 ++ .../java/introspect/impl/ScopeProcessor.java | 61 + .../java/introspect/impl/ServiceProcessor.java | 165 +++ .../impl/ServiceTypeNotFoundException.java | 35 + .../impl/UnknownContextTypeException.java | 33 + ...a.implementation.java.JavaImplementationFactory | 18 + .../introspect/impl/AbstractProcessorTest.java | 76 ++ .../impl/AbstractPropertyProcessorTestCase.java | 169 +++ .../AllowsPassByReferenceProcessorTestCase.java | 71 + .../impl/ConstructorProcessorTestCase.java | 192 +++ .../impl/ConstructorPropertyTestCase.java | 157 +++ .../impl/ConstructorReferenceTestCase.java | 167 +++ .../impl/ConstructorResourceTestCase.java | 152 +++ .../introspect/impl/ContextProcessorTestCase.java | 201 +++ .../impl/ConversationIDProcessorTestCase.java | 92 ++ .../impl/ConversationProcessorTestCase.java | 144 ++ .../introspect/impl/ConvertTimeMillisTestCase.java | 117 ++ .../introspect/impl/DestroyProcessorTestCase.java | 99 ++ .../impl/EagerInitProcessorTestCase.java | 59 + .../impl/HeuristicAndPropertyTestCase.java | 71 + .../impl/HeuristicConstructorTestCase.java | 310 +++++ .../impl/HeuristicPojoProcessorTestCase.java | 407 ++++++ .../HeutisticExtensibleConstructorTestCase.java | 148 ++ .../introspect/impl/InitProcessorTestCase.java | 99 ++ .../impl/JavaClassIntrospectorImplTestCase.java | 95 ++ .../java/introspect/impl/ModelHelper.java | 99 ++ .../introspect/impl/PolicyProcessorTestCase.java | 418 ++++++ .../introspect/impl/PropertyProcessorTestCase.java | 212 +++ .../impl/ReferenceProcessorTestCase.java | 221 +++ .../introspect/impl/ResourceProcessorTestCase.java | 119 ++ .../introspect/impl/ScopeProcessorTestCase.java | 113 ++ .../introspect/impl/ServiceCallbackTestCase.java | 183 +++ .../introspect/impl/ServiceProcessorTestCase.java | 143 ++ branches/sca-android/tuscany-policy-xml/.classpath | 29 + branches/sca-android/tuscany-policy-xml/.project | 20 + .../.settings/org.eclipse.jdt.core.prefs | 5 + branches/sca-android/tuscany-policy-xml/DISCLAIMER | 8 + branches/sca-android/tuscany-policy-xml/LICENSE | 205 +++ branches/sca-android/tuscany-policy-xml/NOTICE | 6 + branches/sca-android/tuscany-policy-xml/pom.xml | 120 ++ .../sca/policy/xml/BindingTypeProcessor.java | 56 + .../policy/xml/ImplementationTypeProcessor.java | 56 + .../policy/xml/IntentAttachPointTypeProcessor.java | 219 +++ .../tuscany/sca/policy/xml/PolicyConstants.java | 77 ++ .../sca/policy/xml/PolicyIntentProcessor.java | 302 +++++ .../tuscany/sca/policy/xml/PolicySetProcessor.java | 479 +++++++ .../sca/policy/xml/ProfileIntentProcessor.java | 38 + .../sca/policy/xml/QualifiedIntentProcessor.java | 43 + .../sca/policy/xml/SimpleIntentProcessor.java | 38 + ...ca.contribution.processor.StAXArtifactProcessor | 22 + .../sca/policy/xml/MockPolicyProcessor.java | 70 + .../sca/policy/xml/ReadDocumentTestCase.java | 251 ++++ .../tuscany/sca/policy/xml/TestModelResolver.java | 63 + .../tuscany/sca/policy/xml/test_definitions.xml | 254 ++++ 804 files changed, 79017 insertions(+) create mode 100644 branches/sca-android/android-jdk-classes/.classpath create mode 100644 branches/sca-android/android-jdk-classes/.project create mode 100644 branches/sca-android/android-jdk-classes/AndroidManifest.xml create mode 100644 branches/sca-android/android-jdk-classes/src/javax/xml/XMLConstants.java create mode 100644 branches/sca-android/android-jdk-classes/src/javax/xml/namespace/QName.java create mode 100644 branches/sca-android/android-jdk-classes/src/javax/xml/transform/Result.java create mode 100644 branches/sca-android/android-jdk-classes/src/javax/xml/transform/Source.java create mode 100644 branches/sca-android/android-jdk-classes/src/javax/xml/transform/dom/DOMSource.java create mode 100644 branches/sca-android/android-jdk-classes/src/javax/xml/transform/sax/SAXSource.java create mode 100644 branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/ContextRegistry.java create mode 100644 branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexResource.java create mode 100644 branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLConnection.java create mode 100644 branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandler.java create mode 100644 branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandlerFactory.java create mode 100644 branches/sca-android/binding-jsonrpc/.classpath create mode 100644 branches/sca-android/binding-jsonrpc/.project create mode 100644 branches/sca-android/binding-jsonrpc/DISCLAIMER create mode 100644 branches/sca-android/binding-jsonrpc/LICENSE create mode 100644 branches/sca-android/binding-jsonrpc/NOTICE create mode 100644 branches/sca-android/binding-jsonrpc/pom.xml create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCBinding.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceServlet.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JavaToSmd.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/ScaDomainScriptServlet.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java create mode 100644 branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor create mode 100644 branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory create mode 100644 branches/sca-android/binding-jsonrpc/src/main/resources/org/apache/tuscany/sca/binding/jsonrpc/jsonrpc.js create mode 100644 branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/Echo.java create mode 100644 branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/EchoComponentImpl.java create mode 100644 branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java create mode 100644 branches/sca-android/binding-jsonrpc/src/test/resources/JSONRPCBinding.composite create mode 100644 branches/sca-android/calculator-android/.classpath create mode 100644 branches/sca-android/calculator-android/.project create mode 100644 branches/sca-android/calculator-android/AndroidManifest.xml create mode 100644 branches/sca-android/calculator-android/res/drawable/icon.png create mode 100644 branches/sca-android/calculator-android/res/layout/main.xml create mode 100644 branches/sca-android/calculator-android/res/raw/calculator_composite create mode 100644 branches/sca-android/calculator-android/res/raw/sca.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_all.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_binding_ejb.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_binding_jms.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_binding_sca.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_binding_webservice.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_core.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_definitions.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_implementation_bpel.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_implementation_composite_xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_implementation_cpp.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_implementation_ejb.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_implementation_java.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_implementation_spring.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_interface_cpp.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_interface_java.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_interface_wsdl.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/sca_policy.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_atom.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_dwr.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_http.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_jsonrpc.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_notification.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rmi.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rss.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_node.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_notification.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_osgi.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_resource.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_script.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_widget.xsd create mode 100644 branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_xquery.xsd create mode 100644 branches/sca-android/calculator-android/res/values/strings.xml create mode 100644 branches/sca-android/calculator-android/src/calculator/AddService.java create mode 100644 branches/sca-android/calculator-android/src/calculator/AddServiceImpl.java create mode 100644 branches/sca-android/calculator-android/src/calculator/CalculatorService.java create mode 100644 branches/sca-android/calculator-android/src/calculator/CalculatorServiceImpl.java create mode 100644 branches/sca-android/calculator-android/src/calculator/DivideService.java create mode 100644 branches/sca-android/calculator-android/src/calculator/DivideServiceImpl.java create mode 100644 branches/sca-android/calculator-android/src/calculator/MultiplyService.java create mode 100644 branches/sca-android/calculator-android/src/calculator/MultiplyServiceImpl.java create mode 100644 branches/sca-android/calculator-android/src/calculator/SubtractService.java create mode 100644 branches/sca-android/calculator-android/src/calculator/SubtractServiceImpl.java create mode 100644 branches/sca-android/calculator-android/src/calculator/android/CalculatorClient.java create mode 100644 branches/sca-android/contribution-impl/.classpath create mode 100644 branches/sca-android/contribution-impl/.project create mode 100644 branches/sca-android/contribution-impl/DISCLAIMER create mode 100644 branches/sca-android/contribution-impl/LICENSE create mode 100644 branches/sca-android/contribution-impl/NOTICE create mode 100644 branches/sca-android/contribution-impl/pom.xml create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/DexContributionProcessor.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/FolderContributionProcessor.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/JarContributionProcessor.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/FileHelper.java create mode 100644 branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/IOHelper.java create mode 100644 branches/sca-android/contribution-impl/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/FolderContributionPackageProcessorTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/JarContributionPackageProcessorTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/ContributionRepositoryTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/PackageTypeDescriberImplTestCase.java create mode 100644 branches/sca-android/contribution-impl/src/test/resources/deployables/sample-calculator.jar create mode 100644 branches/sca-android/contribution-impl/src/test/resources/repository/sample-calculator.jar create mode 100644 branches/sca-android/contribution-impl/src/test/resources/test.composite create mode 100644 branches/sca-android/contribution-impl/src/test/resources/test.ext create mode 100644 branches/sca-android/contribution/.classpath create mode 100644 branches/sca-android/contribution/.project create mode 100644 branches/sca-android/contribution/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/contribution/DISCLAIMER create mode 100644 branches/sca-android/contribution/LICENSE create mode 100644 branches/sca-android/contribution/NOTICE create mode 100644 branches/sca-android/contribution/pom.xml create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java create mode 100644 branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint create mode 100644 branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint create mode 100644 branches/sca-android/core-android/.classpath create mode 100644 branches/sca-android/core-android/.project create mode 100644 branches/sca-android/core-android/DISCLAIMER create mode 100644 branches/sca-android/core-android/LICENSE create mode 100644 branches/sca-android/core-android/NOTICE create mode 100644 branches/sca-android/core-android/pom.xml create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivatorImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/EndpointReferenceImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParameterProcessor.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParametersImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentReferenceImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentServiceImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeWireImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextHelper.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/InstanceWrapper.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/RequestContextImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManagerImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversation.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversationImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/BaseEventPublisher.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStart.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStop.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationEnd.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationStart.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionEnd.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionStart.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestEnd.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestStart.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/InvocationChainImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKCallbackInvocationHandler.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKProxyFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageFactoryImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NoMethodForOperationException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseManager.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseSorter.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/TargetInvocationException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainerFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainerFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainerFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainerFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistryImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainer.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainerFactory.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/store/MemoryStore.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237Work.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237WorkScheduler.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/ThreadPoolWorkManager.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkEventImpl.java create mode 100644 branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkItemImpl.java create mode 100644 branches/sca-android/core-android/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistryTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/BaseEventPublisherTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/EventTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseManagerTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseSorterTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainerTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/store/MemoryStoreTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/CallbackInterfaceInterceptorTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/InvocationChainImplTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/NonBlockingInterceptorTestCase.java create mode 100644 branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java create mode 100644 branches/sca-android/core-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest create mode 100644 branches/sca-android/core-databinding/.classpath create mode 100644 branches/sca-android/core-databinding/.project create mode 100644 branches/sca-android/core-databinding/DISCLAIMER create mode 100644 branches/sca-android/core-databinding/LICENSE create mode 100644 branches/sca-android/core-databinding/NOTICE create mode 100644 branches/sca-android/core-databinding/pom.xml create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java create mode 100644 branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java create mode 100644 branches/sca-android/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator create mode 100644 branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessorTestCase.java create mode 100644 branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/transformers/IDLTransformerTestCase.java.fixme create mode 100644 branches/sca-android/extensibility/.classpath create mode 100644 branches/sca-android/extensibility/.project create mode 100644 branches/sca-android/extensibility/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/extensibility/DISCLAIMER create mode 100644 branches/sca-android/extensibility/LICENSE create mode 100644 branches/sca-android/extensibility/NOTICE create mode 100644 branches/sca-android/extensibility/pom.xml create mode 100644 branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java create mode 100644 branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java create mode 100644 branches/sca-android/host-android/.classpath create mode 100644 branches/sca-android/host-android/.project create mode 100644 branches/sca-android/host-android/DISCLAIMER create mode 100644 branches/sca-android/host-android/LICENSE create mode 100644 branches/sca-android/host-android/NOTICE create mode 100644 branches/sca-android/host-android/pom.xml create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java create mode 100644 branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java create mode 100644 branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java create mode 100644 branches/sca-android/host-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator create mode 100644 branches/sca-android/host-android/src/test/resources/test.composite create mode 100644 branches/sca-android/host-android/src/test/resources/test.txt create mode 100644 branches/sca-android/interface-java-jaxws/.classpath create mode 100644 branches/sca-android/interface-java-jaxws/.project create mode 100644 branches/sca-android/interface-java-jaxws/DISCLAIMER create mode 100644 branches/sca-android/interface-java-jaxws/LICENSE create mode 100644 branches/sca-android/interface-java-jaxws/NOTICE create mode 100644 branches/sca-android/interface-java-jaxws/pom.xml create mode 100644 branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java create mode 100644 branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java create mode 100644 branches/sca-android/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl create mode 100644 branches/sca-android/interface-java/.classpath create mode 100644 branches/sca-android/interface-java/.project create mode 100644 branches/sca-android/interface-java/DISCLAIMER create mode 100644 branches/sca-android/interface-java/LICENSE create mode 100644 branches/sca-android/interface-java/NOTICE create mode 100644 branches/sca-android/interface-java/pom.xml create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java create mode 100644 branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java create mode 100644 branches/sca-android/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory create mode 100644 branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.java create mode 100644 branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.java create mode 100644 branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java create mode 100644 branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java create mode 100644 branches/sca-android/retrotranslator_readme create mode 100644 branches/sca-android/tuscany-assembly-xml/.classpath create mode 100644 branches/sca-android/tuscany-assembly-xml/.project create mode 100644 branches/sca-android/tuscany-assembly-xml/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-assembly-xml/DISCLAIMER create mode 100644 branches/sca-android/tuscany-assembly-xml/LICENSE create mode 100644 branches/sca-android/tuscany-assembly-xml/NOTICE create mode 100644 branches/sca-android/tuscany-assembly-xml/pom.xml create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeDocumentProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeModelResolver.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeDocumentProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeModelResolver.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConfiguredOperationProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/Constants.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeDocumentProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeModelResolver.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/DefaultBeanModelProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/PolicyAttachPointProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/BuildPolicyTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/MockPolicyProcessor.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadAllTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadDocumentTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolvePolicyTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolveTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestModelResolver.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingFactoryImpl.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingImpl.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WireTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WriteAllTestCase.java create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/Calculator.composite create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorComponent.constrainingType create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorImpl.componentType create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/JavaScriptReference.composite create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/RMIBindingTest.composite create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllCalculator.composite create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllDivide.composite create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllPolicyCalculator.composite create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/another_test_definitions.xml create mode 100644 branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/test_definitions.xml create mode 100644 branches/sca-android/tuscany-assembly/.classpath create mode 100644 branches/sca-android/tuscany-assembly/.project create mode 100644 branches/sca-android/tuscany-assembly/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-assembly/DISCLAIMER create mode 100644 branches/sca-android/tuscany-assembly/LICENSE create mode 100644 branches/sca-android/tuscany-assembly/NOTICE create mode 100644 branches/sca-android/tuscany-assembly/pom.xml create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractContract.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractProperty.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractReference.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractService.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AssemblyFactory.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Base.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Binding.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Callback.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Component.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentProperty.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentReference.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentService.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentType.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Composite.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeReference.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeService.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConfiguredOperation.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConstrainingType.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Contract.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/DefaultAssemblyFactory.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Extensible.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Implementation.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Multiplicity.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OperationsConfigurator.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OptimizableBinding.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Property.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Reference.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABinding.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABindingFactory.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Service.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Wire.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderMonitor.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/Problem.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingPolicyComputer.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingUtil.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeConfigurationBuilderImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeWireBuilderImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/DomainWireBuilderImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ImplementationPolicyComputer.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputationException.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputer.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyUtil.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceUtil.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractPropertyImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractReferenceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractServiceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AssemblyFactoryImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/BaseImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CallbackImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentPropertyImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentReferenceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentServiceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentTypeImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeReferenceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeServiceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConfiguredOperationImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConstrainingTypeImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ContractImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ExtensibleImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ImplementationImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/PropertyImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ReferenceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ServiceImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/WireImpl.java create mode 100644 branches/sca-android/tuscany-assembly/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/AssemblyFactoryTestCase.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestBinding.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestImplementation.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterface.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterfaceContract.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestOperation.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CalculateBindingURITestCase.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderTestCase.java create mode 100644 branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtilTestCase.java create mode 100644 branches/sca-android/tuscany-core-spi/.classpath create mode 100644 branches/sca-android/tuscany-core-spi/.project create mode 100644 branches/sca-android/tuscany-core-spi/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-core-spi/DISCLAIMER create mode 100644 branches/sca-android/tuscany-core-spi/LICENSE create mode 100644 branches/sca-android/tuscany-core-spi/NOTICE create mode 100644 branches/sca-android/tuscany-core-spi/pom.xml create mode 100644 branches/sca-android/tuscany-core-spi/src/doc/Context Model.emx create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistry.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ExtensionPointRegistry.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ModuleActivator.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/Event.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventFilter.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventPublisher.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/RuntimeEventListener.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/TrueFilter.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultSCADefinitionsProviderExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProvider.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderException.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReference.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWire.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/DuplicateRecordException.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/RecoveryListener.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/Store.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreException.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreExpirationEvent.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreMonitor.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreReadException.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreWriteException.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.java create mode 100644 branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint create mode 100644 branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint create mode 100644 branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/.classpath create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/.project create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/DISCLAIMER create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/LICENSE create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/NOTICE create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/pom.xml create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaPolicyHandlingRuntimeWireProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PolicyHandlingInterceptor.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactoryTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/.classpath create mode 100644 branches/sca-android/tuscany-implementation-java-xml/.project create mode 100644 branches/sca-android/tuscany-implementation-java-xml/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-implementation-java-xml/DISCLAIMER create mode 100644 branches/sca-android/tuscany-implementation-java-xml/LICENSE create mode 100644 branches/sca-android/tuscany-implementation-java-xml/NOTICE create mode 100644 branches/sca-android/tuscany-implementation-java-xml/pom.xml create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddService.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddServiceImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorService.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideService.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyService.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractService.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions.xml create mode 100644 branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions_with_policysets.xml create mode 100644 branches/sca-android/tuscany-implementation-java/.classpath create mode 100644 branches/sca-android/tuscany-implementation-java/.project create mode 100644 branches/sca-android/tuscany-implementation-java/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-implementation-java/DISCLAIMER create mode 100644 branches/sca-android/tuscany-implementation-java/LICENSE create mode 100644 branches/sca-android/tuscany-implementation-java/NOTICE create mode 100644 branches/sca-android/tuscany-implementation-java/pom.xml create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/BaseJavaImplementation.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/DefaultJavaImplementationFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/IntrospectionException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementation.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementationFactory.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/BaseJavaImplementationImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaClassIntrospectorImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaConstructorImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationFactoryImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaParameterImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaResourceImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaScopeImpl.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ComponentNameProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicatePropertyException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalPropertyException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/Resource.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.JavaImplementationFactory create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaClassIntrospectorImplTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java create mode 100644 branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java create mode 100644 branches/sca-android/tuscany-policy-xml/.classpath create mode 100644 branches/sca-android/tuscany-policy-xml/.project create mode 100644 branches/sca-android/tuscany-policy-xml/.settings/org.eclipse.jdt.core.prefs create mode 100644 branches/sca-android/tuscany-policy-xml/DISCLAIMER create mode 100644 branches/sca-android/tuscany-policy-xml/LICENSE create mode 100644 branches/sca-android/tuscany-policy-xml/NOTICE create mode 100644 branches/sca-android/tuscany-policy-xml/pom.xml create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/BindingTypeProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ImplementationTypeProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentAttachPointTypeProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyConstants.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyIntentProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ProfileIntentProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/QualifiedIntentProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/SimpleIntentProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor create mode 100644 branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/MockPolicyProcessor.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/ReadDocumentTestCase.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/TestModelResolver.java create mode 100644 branches/sca-android/tuscany-policy-xml/src/test/resources/org/apache/tuscany/sca/policy/xml/test_definitions.xml diff --git a/branches/sca-android/android-jdk-classes/.classpath b/branches/sca-android/android-jdk-classes/.classpath new file mode 100644 index 0000000000..168313b5c6 --- /dev/null +++ b/branches/sca-android/android-jdk-classes/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/branches/sca-android/android-jdk-classes/.project b/branches/sca-android/android-jdk-classes/.project new file mode 100644 index 0000000000..a9a7150930 --- /dev/null +++ b/branches/sca-android/android-jdk-classes/.project @@ -0,0 +1,17 @@ + + + android-jdk-classes + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/branches/sca-android/android-jdk-classes/AndroidManifest.xml b/branches/sca-android/android-jdk-classes/AndroidManifest.xml new file mode 100644 index 0000000000..8f419508ce --- /dev/null +++ b/branches/sca-android/android-jdk-classes/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/android-jdk-classes/src/javax/xml/XMLConstants.java b/branches/sca-android/android-jdk-classes/src/javax/xml/XMLConstants.java new file mode 100644 index 0000000000..2159723b20 --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/javax/xml/XMLConstants.java @@ -0,0 +1,196 @@ +/* + * The contents of this file are subject to the terms + * of the Common Development and Distribution License + * (the "License"). You may not use this file except + * in compliance with the License. + * + * You can obtain a copy of the license at + * https://jaxp.dev.java.net/CDDLv1.0.html. + * See the License for the specific language governing + * permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL + * HEADER in each file and include the License file at + * https://jaxp.dev.java.net/CDDLv1.0.html + * If applicable add the following below this CDDL HEADER + * with the fields enclosed by brackets "[]" replaced with + * your own identifying information: Portions Copyright + * [year] [name of copyright owner] + */ + +/* + * $Id: XMLEntityReader.java,v 1.3 2005/11/03 17:02:21 jeffsuttor Exp $ + * @(#)XMLConstants.java 1.15 05/11/17 + * + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + */ + +package javax.xml; + +/** + *

Utility class to contain basic XML values as constants.

+ * + * @author Jeff Suttor + * @version $Revision: 1.2 $, $Date: 2005/06/10 03:50:26 $ + * @see Extensible Markup Language (XML) 1.1 + * @see Extensible Markup Language (XML) 1.0 (Second Edition) + * @see XML 1.0 Second Edition Specification Errata + * @see Namespaces in XML 1.1 + * @see Namespaces in XML + * @see Namespaces in XML Errata + * @see XML Schema Part 1: Structures + * @since 1.5 + **/ + +public final class XMLConstants { + + /** + *

Private constructor to prevent instantiation.

+ */ + private XMLConstants() { + } + + /** + *

Namespace URI to use to represent that there is no Namespace.

+ * + *

Defined by the Namespace specification to be "".

+ * + * @see + * Namespaces in XML, 5.2 Namespace Defaulting + */ + public static final String NULL_NS_URI = ""; + + /** + *

Prefix to use to represent the default XML Namespace.

+ * + *

Defined by the XML specification to be "".

+ * + * @see + * Namespaces in XML, 3. Qualified Names + */ + public static final String DEFAULT_NS_PREFIX = ""; + + /** + *

The official XML Namespace name URI.

+ * + *

Defined by the XML specification to be + * "http://www.w3.org/XML/1998/namespace".

+ * + * @see + * Namespaces in XML, 3. Qualified Names + */ + public static final String XML_NS_URI = + "http://www.w3.org/XML/1998/namespace"; + + /** + *

The official XML Namespace prefix.

+ * + *

Defined by the XML specification to be "xml".

+ * + * @see + * Namespaces in XML, 3. Qualified Names< + */ + public static final String XML_NS_PREFIX = "xml"; + + /** + *

The official XML attribute used for specifying XML Namespace + * declarations, {@link #XMLNS_ATTRIBUTE + * XMLConstants.XMLNS_ATTRIBUTE}, Namespace name URI.

+ * + *

Defined by the XML specification to be + * "http://www.w3.org/2000/xmlns/".

+ * + * @see + * Namespaces in XML, 3. Qualified Names + * @see + * Namespaces in XML Errata + */ + public static final String XMLNS_ATTRIBUTE_NS_URI = + "http://www.w3.org/2000/xmlns/"; + + /** + *

The official XML attribute used for specifying XML Namespace + * declarations.

+ * + *

It is NOT valid to use as a + * prefix. Defined by the XML specification to be + * "xmlns".

+ * + * @see + * Namespaces in XML, 3. Qualified Names + */ + public static final String XMLNS_ATTRIBUTE = "xmlns"; + + /** + *

W3C XML Schema Namespace URI.

+ * + *

Defined to be "http://www.w3.org/2001/XMLSchema". + * + * @see + * XML Schema Part 1: + * Structures, 2.6 Schema-Related Markup in Documents Being Validated + */ + public static final String W3C_XML_SCHEMA_NS_URI = + "http://www.w3.org/2001/XMLSchema"; + + /** + *

W3C XML Schema Instance Namespace URI.

+ * + *

Defined to be "http://www.w3.org/2001/XMLSchema-instance".

+ * + * @see + * XML Schema Part 1: + * Structures, 2.6 Schema-Related Markup in Documents Being Validated + */ + public static final String W3C_XML_SCHEMA_INSTANCE_NS_URI = + "http://www.w3.org/2001/XMLSchema-instance"; + + /** + *

W3C XPath Datatype Namespace URI.

+ * + *

Defined to be "http://www.w3.org/2003/11/xpath-datatypes".

+ * + * @see XQuery 1.0 and XPath 2.0 Data Model + */ + public static final String W3C_XPATH_DATATYPE_NS_URI = "http://www.w3.org/2003/11/xpath-datatypes"; + + /** + *

XML Document Type Declaration Namespace URI as an arbitrary value.

+ * + *

Since not formally defined by any existing standard, arbitrarily define to be "http://www.w3.org/TR/REC-xml". + */ + public static final String XML_DTD_NS_URI = "http://www.w3.org/TR/REC-xml"; + + /** + *

RELAX NG Namespace URI.

+ * + *

Defined to be "http://relaxng.org/ns/structure/1.0".

+ * + * @see RELAX NG Specification + */ + public static final String RELAXNG_NS_URI = "http://relaxng.org/ns/structure/1.0"; + + /** + *

Feature for secure processing.

+ * + * + */ + public static final String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing"; +} diff --git a/branches/sca-android/android-jdk-classes/src/javax/xml/namespace/QName.java b/branches/sca-android/android-jdk-classes/src/javax/xml/namespace/QName.java new file mode 100644 index 0000000000..3461dd1cab --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/javax/xml/namespace/QName.java @@ -0,0 +1,515 @@ + +/* + * The contents of this file are subject to the terms + * of the Common Development and Distribution License + * (the "License"). You may not use this file except + * in compliance with the License. + * + * You can obtain a copy of the license at + * https://jaxp.dev.java.net/CDDLv1.0.html. + * See the License for the specific language governing + * permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL + * HEADER in each file and include the License file at + * https://jaxp.dev.java.net/CDDLv1.0.html + * If applicable add the following below this CDDL HEADER + * with the fields enclosed by brackets "[]" replaced with + * your own identifying information: Portions Copyright + * [year] [name of copyright owner] + */ + +/* + * $Id: QName.java,v 1.5 2005/11/03 19:34:20 jeffsuttor Exp $ + * @(#)QName.java 1.17 06/04/07 + * + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + */ + +package javax.xml.namespace; + +import java.io.Serializable; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.xml.XMLConstants; + +/** + *

QName represents a qualified name + * as defined in the XML specifications: XML Schema Part2: + * Datatypes specification, Namespaces + * in XML, Namespaces + * in XML Errata.

+ * + *

The value of a QName contains a Namespace + * URI, local part and + * prefix.

+ * + *

The prefix is included in QName to retain lexical + * information when present in an {@link + * javax.xml.transform.Source XML input source}. The prefix is + * NOT used in {@link #equals(Object) + * QName.equals(Object)} or to compute the {@link #hashCode() + * QName.hashCode()}. Equality and the hash code are defined using + * only the Namespace URI and local part.

+ * + *

If not specified, the Namespace URI is set to {@link + * javax.xml.XMLConstants#NULL_NS_URI XMLConstants.NULL_NS_URI}. + * If not specified, the prefix is set to {@link + * javax.xml.XMLConstants#DEFAULT_NS_PREFIX + * XMLConstants.DEFAULT_NS_PREFIX}.

+ * + *

QName is immutable.

+ * + * @author Jeff Suttor + * @version $Revision: 1.5 $, $Date: 2005/11/03 19:34:20 $ + * @see + * XML Schema Part2: Datatypes specification + * @see + * Namespaces in XML + * @see + * Namespaces in XML Errata + * @since 1.5 + */ + +public class QName implements Serializable { + + /** + *

Stream Unique Identifier.

+ * + *

Due to a historical defect, QName was released with multiple + * serialVersionUID values even though its serialization was the + * same.

+ * + *

To workaround this issue, serialVersionUID is set with either + * a default value or a compatibility value. To use the + * compatiblity value, set the system property:

+ * + * com.sun.xml.namespace.QName.useCompatibleSerialVersionUID=1.0 + * + *

This workaround was inspired by classes in the javax.management + * package, e.g. ObjectName, etc. + * See CR6267224 for original defect report.

+ */ + private static final long serialVersionUID; + /** + *

Default serialVersionUID value.

+ */ + private static final long defaultSerialVersionUID = -9120448754896609940L; + /** + *

Compatibility serialVersionUID value.

+ */ + private static final long compatibleSerialVersionUID = 4418622981026545151L; + /** + *

Flag to use default or campatible serialVersionUID.

+ */ + private static boolean useDefaultSerialVersionUID = true; + static { + try { + // use a privileged block as reading a system property + String valueUseCompatibleSerialVersionUID = (String) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + return System.getProperty("com.sun.xml.namespace.QName.useCompatibleSerialVersionUID"); + } + } + ); + useDefaultSerialVersionUID = (valueUseCompatibleSerialVersionUID != null && valueUseCompatibleSerialVersionUID.equals("1.0")) ? false : true; + } catch (Exception exception) { + // use default if any Exceptions + useDefaultSerialVersionUID = true; + } + + // set serialVersionUID to desired value + if (useDefaultSerialVersionUID) { + serialVersionUID = defaultSerialVersionUID; + } else { + serialVersionUID = compatibleSerialVersionUID; + } + } + + /** + *

Namespace URI of this QName.

+ */ + private final String namespaceURI; + + /** + *

local part of this QName.

+ */ + private final String localPart; + + /** + *

prefix of this QName.

+ */ + private final String prefix; + + /** + *

QName constructor specifying the Namespace URI + * and local part.

+ * + *

If the Namespace URI is null, it is set to + * {@link javax.xml.XMLConstants#NULL_NS_URI + * XMLConstants.NULL_NS_URI}. This value represents no + * explicitly defined Namespace as defined by the Namespaces + * in XML specification. This action preserves compatible + * behavior with QName 1.0. Explicitly providing the {@link + * javax.xml.XMLConstants#NULL_NS_URI + * XMLConstants.NULL_NS_URI} value is the preferred coding + * style.

+ * + *

If the local part is null an + * IllegalArgumentException is thrown. + * A local part of "" is allowed to preserve + * compatible behavior with QName 1.0.

+ * + *

When using this constructor, the prefix is set to {@link + * javax.xml.XMLConstants#DEFAULT_NS_PREFIX + * XMLConstants.DEFAULT_NS_PREFIX}.

+ * + *

The Namespace URI is not validated as a + * URI reference. + * The local part is not validated as a + * NCName + * as specified in Namespaces + * in XML.

+ * + * @param namespaceURI Namespace URI of the QName + * @param localPart local part of the QName + * + * @throws IllegalArgumentException When localPart is + * null + * + * @see #QName(String namespaceURI, String localPart, String + * prefix) QName(String namespaceURI, String localPart, String + * prefix) + */ + public QName(final String namespaceURI, final String localPart) { + this(namespaceURI, localPart, XMLConstants.DEFAULT_NS_PREFIX); + } + + /** + *

QName constructor specifying the Namespace URI, + * local part and prefix.

+ * + *

If the Namespace URI is null, it is set to + * {@link javax.xml.XMLConstants#NULL_NS_URI + * XMLConstants.NULL_NS_URI}. This value represents no + * explicitly defined Namespace as defined by the Namespaces + * in XML specification. This action preserves compatible + * behavior with QName 1.0. Explicitly providing the {@link + * javax.xml.XMLConstants#NULL_NS_URI + * XMLConstants.NULL_NS_URI} value is the preferred coding + * style.

+ * + *

If the local part is null an + * IllegalArgumentException is thrown. + * A local part of "" is allowed to preserve + * compatible behavior with QName 1.0.

+ * + *

If the prefix is null, an + * IllegalArgumentException is thrown. Use {@link + * javax.xml.XMLConstants#DEFAULT_NS_PREFIX + * XMLConstants.DEFAULT_NS_PREFIX} to explicitly indicate that no + * prefix is present or the prefix is not relevant.

+ * + *

The Namespace URI is not validated as a + * URI reference. + * The local part and prefix are not validated as a + * NCName + * as specified in Namespaces + * in XML.

+ * + * @param namespaceURI Namespace URI of the QName + * @param localPart local part of the QName + * @param prefix prefix of the QName + * + * @throws IllegalArgumentException When localPart + * or prefix is null + */ + public QName(String namespaceURI, String localPart, String prefix) { + + // map null Namespace URI to default + // to preserve compatibility with QName 1.0 + if (namespaceURI == null) { + this.namespaceURI = XMLConstants.NULL_NS_URI; + } else { + this.namespaceURI = namespaceURI; + } + + // local part is required. + // "" is allowed to preserve compatibility with QName 1.0 + if (localPart == null) { + throw new IllegalArgumentException( + "local part cannot be \"null\" when creating a QName"); + } + this.localPart = localPart; + + // prefix is required + if (prefix == null) { + throw new IllegalArgumentException( + "prefix cannot be \"null\" when creating a QName"); + } + this.prefix = prefix; + } + + /** + *

QName constructor specifying the local part.

+ * + *

If the local part is null an + * IllegalArgumentException is thrown. + * A local part of "" is allowed to preserve + * compatible behavior with QName 1.0.

+ * + *

When using this constructor, the Namespace URI is set to + * {@link javax.xml.XMLConstants#NULL_NS_URI + * XMLConstants.NULL_NS_URI} and the prefix is set to {@link + * javax.xml.XMLConstants#DEFAULT_NS_PREFIX + * XMLConstants.DEFAULT_NS_PREFIX}.

+ * + *

In an XML context, all Element and Attribute names exist + * in the context of a Namespace. Making this explicit during the + * construction of a QName helps prevent hard to + * diagnosis XML validity errors. The constructors {@link + * #QName(String namespaceURI, String localPart) QName(String + * namespaceURI, String localPart)} and + * {@link #QName(String namespaceURI, String localPart, String prefix)} + * are preferred.

+ * + *

The local part is not validated as a + * NCName + * as specified in Namespaces + * in XML.

+ * + * @param localPart local part of the QName + * + * @throws IllegalArgumentException When localPart is + * null + * + * @see #QName(String namespaceURI, String localPart) QName(String + * namespaceURI, String localPart) + * @see #QName(String namespaceURI, String localPart, String + * prefix) QName(String namespaceURI, String localPart, String + * prefix) + */ + public QName(String localPart) { + this( + XMLConstants.NULL_NS_URI, + localPart, + XMLConstants.DEFAULT_NS_PREFIX); + } + + /** + *

Get the Namespace URI of this QName.

+ * + * @return Namespace URI of this QName + */ + public String getNamespaceURI() { + return namespaceURI; + } + + /** + *

Get the local part of this QName.

+ * + * @return local part of this QName + */ + public String getLocalPart() { + return localPart; + } + + /** + *

Get the prefix of this QName.

+ * + *

The prefix assigned to a QName might + * NOT be valid in a different + * context. For example, a QName may be assigned a + * prefix in the context of parsing a document but that prefix may + * be invalid in the context of a different document.

+ * + * @return prefix of this QName + */ + public String getPrefix() { + return prefix; + } + + /** + *

Test this QName for equality with another + * Object.

+ * + *

If the Object to be tested is not a + * QName or is null, then this method + * returns false.

+ * + *

Two QNames are considered equal if and only if + * both the Namespace URI and local part are equal. This method + * uses String.equals() to check equality of the + * Namespace URI and local part. The prefix is + * NOT used to determine equality.

+ * + *

This method satisfies the general contract of {@link + * java.lang.Object#equals(Object) Object.equals(Object)}

+ * + * @param objectToTest the Object to test for + * equality with this QName + * @return true if the given Object is + * equal to this QName else false + */ + public final boolean equals(Object objectToTest) { + if (objectToTest == null || !(objectToTest instanceof QName)) { + return false; + } + + QName qName = (QName) objectToTest; + + return namespaceURI.equals(qName.namespaceURI) + && localPart.equals(qName.localPart); + } + + /** + *

Generate the hash code for this QName.

+ * + *

The hash code is calculated using both the Namespace URI and + * the local part of the QName. The prefix is + * NOT used to calculate the hash + * code.

+ * + *

This method satisfies the general contract of {@link + * java.lang.Object#hashCode() Object.hashCode()}.

+ * + * @return hash code for this QName Object + */ + public final int hashCode() { + return namespaceURI.hashCode() ^ localPart.hashCode(); + } + + /** + *

String representation of this + * QName.

+ * + *

The commonly accepted way of representing a QName + * as a String was + * defined + * by James Clark. Although this is not a standard + * specification, it is in common use, e.g. {@link + * javax.xml.transform.Transformer#setParameter(String name, Object value)}. + * This implementation represents a QName as: + * "{" + Namespace URI + "}" + local part. If the Namespace URI + * .equals(XMLConstants.NULL_NS_URI), only the + * local part is returned. An appropriate use of this method is + * for debugging or logging for human consumption.

+ * + *

Note the prefix value is NOT + * returned as part of the String representation.

+ * + *

This method satisfies the general contract of {@link + * java.lang.Object#toString() Object.toString()}.

+ * + * @return String representation of this QName + */ + public String toString() { + if (namespaceURI.equals(XMLConstants.NULL_NS_URI)) { + return localPart; + } else { + return "{" + namespaceURI + "}" + localPart; + } + } + + /** + *

QName derived from parsing the formatted + * String.

+ * + *

If the String is null or does not conform to + * {@link #toString() QName.toString()} formatting, an + * IllegalArgumentException is thrown.

+ * + *

The String MUST be in the + * form returned by {@link #toString() QName.toString()}.

+ * + *

The commonly accepted way of representing a QName + * as a String was + * defined + * by James Clark. Although this is not a standard + * specification, it is in common use, e.g. {@link + * javax.xml.transform.Transformer#setParameter(String name, Object value)}. + * This implementation parses a String formatted + * as: "{" + Namespace URI + "}" + local part. If the Namespace + * URI .equals(XMLConstants.NULL_NS_URI), only the + * local part should be provided.

+ * + *

The prefix value CANNOT be + * represented in the String and will be set to + * {@link javax.xml.XMLConstants#DEFAULT_NS_PREFIX + * XMLConstants.DEFAULT_NS_PREFIX}.

+ * + *

This method does not do full validation of the resulting + * QName. + *

The Namespace URI is not validated as a + * URI reference. + * The local part is not validated as a + * NCName + * as specified in + * Namespaces in XML.

+ * + * @param qNameAsString String representation + * of the QName + * + * @throws IllegalArgumentException When qNameAsString is + * null or malformed + * + * @return QName corresponding to the given String + * @see #toString() QName.toString() + */ + public static QName valueOf(String qNameAsString) { + + // null is not valid + if (qNameAsString == null) { + throw new IllegalArgumentException( + "cannot create QName from \"null\" or \"\" String"); + } + + // "" local part is valid to preserve compatible behavior with QName 1.0 + if (qNameAsString.length() == 0) { + return new QName( + XMLConstants.NULL_NS_URI, + qNameAsString, + XMLConstants.DEFAULT_NS_PREFIX); + } + + // local part only? + if (qNameAsString.charAt(0) != '{') { + return new QName( + XMLConstants.NULL_NS_URI, + qNameAsString, + XMLConstants.DEFAULT_NS_PREFIX); + } + + // Namespace URI improperly specified? + if (qNameAsString.startsWith("{" + XMLConstants.NULL_NS_URI + "}")) { + throw new IllegalArgumentException( + "Namespace URI .equals(XMLConstants.NULL_NS_URI), " + + ".equals(\"" + XMLConstants.NULL_NS_URI + "\"), " + + "only the local part, " + + "\"" + + qNameAsString.substring(2 + XMLConstants.NULL_NS_URI.length()) + + "\", " + + "should be provided."); + } + + // Namespace URI and local part specified + int endOfNamespaceURI = qNameAsString.indexOf('}'); + if (endOfNamespaceURI == -1) { + throw new IllegalArgumentException( + "cannot create QName from \"" + + qNameAsString + + "\", missing closing \"}\""); + } + return new QName( + qNameAsString.substring(1, endOfNamespaceURI), + qNameAsString.substring(endOfNamespaceURI + 1), + XMLConstants.DEFAULT_NS_PREFIX); + } +} diff --git a/branches/sca-android/android-jdk-classes/src/javax/xml/transform/Result.java b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/Result.java new file mode 100644 index 0000000000..dd3517c8cc --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/Result.java @@ -0,0 +1,70 @@ +// $Id: Result.java,v 1.2 2003/10/22 03:53:16 jsuttor Exp $ + +/* + * @(#)Result.java 1.13 04/07/26 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package javax.xml.transform; + +/** + *

An object that implements this interface contains the information + * needed to build a transformation result tree.

+ * + * @author Jeff Suttor + */ +public interface Result { + + /** + * The name of the processing instruction that is sent if the + * result tree disables output escaping. + * + *

Normally, result tree serialization escapes & and < (and + * possibly other characters) when outputting text nodes. + * This ensures that the output is well-formed XML. However, + * it is sometimes convenient to be able to produce output that is + * almost, but not quite well-formed XML; for example, + * the output may include ill-formed sections that will + * be transformed into well-formed XML by a subsequent non-XML aware + * process. If a processing instruction is sent with this name, + * serialization should be output without any escaping.

+ * + *

Result DOM trees may also have PI_DISABLE_OUTPUT_ESCAPING and + * PI_ENABLE_OUTPUT_ESCAPING inserted into the tree.

+ * + * @see disable-output-escaping in XSLT Specification + */ + public static final String PI_DISABLE_OUTPUT_ESCAPING = + "javax.xml.transform.disable-output-escaping"; + + /** + * The name of the processing instruction that is sent + * if the result tree enables output escaping at some point after having + * received a PI_DISABLE_OUTPUT_ESCAPING processing instruction. + * + * @see disable-output-escaping in XSLT Specification + */ + public static final String PI_ENABLE_OUTPUT_ESCAPING = + "javax.xml.transform.enable-output-escaping"; + + /** + * Set the system identifier for this Result. + * + *

If the Result is not to be written to a file, the system identifier is optional. + * The application may still want to provide one, however, for use in error messages + * and warnings, or to resolve relative output identifiers.

+ * + * @param systemId The system identifier as a URI string. + */ + public void setSystemId(String systemId); + + /** + * Get the system identifier that was set with setSystemId. + * + * @return The system identifier that was set with setSystemId, + * or null if setSystemId was not called. + */ + public String getSystemId(); +} diff --git a/branches/sca-android/android-jdk-classes/src/javax/xml/transform/Source.java b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/Source.java new file mode 100644 index 0000000000..5467229cc7 --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/Source.java @@ -0,0 +1,36 @@ +// $Id: Source.java,v 1.2 2003/09/07 23:02:09 jsuttor Exp $ +/* + * @(#)Source.java 1.14 04/07/26 + * + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package javax.xml.transform; + +/** + * An object that implements this interface contains the information + * needed to act as source input (XML source or transformation instructions). + */ +public interface Source { + + /** + * Set the system identifier for this Source. + * + *

The system identifier is optional if the source does not + * get its data from a URL, but it may still be useful to provide one. + * The application can use a system identifier, for example, to resolve + * relative URIs and to include in error messages and warnings.

+ * + * @param systemId The system identifier as a URL string. + */ + public void setSystemId(String systemId); + + /** + * Get the system identifier that was set with setSystemId. + * + * @return The system identifier that was set with setSystemId, or null + * if setSystemId was not called. + */ + public String getSystemId(); +} diff --git a/branches/sca-android/android-jdk-classes/src/javax/xml/transform/dom/DOMSource.java b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/dom/DOMSource.java new file mode 100644 index 0000000000..a55864a04c --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/dom/DOMSource.java @@ -0,0 +1,122 @@ +// $Id: DOMSource.java,v 1.5.14.1.2.2 2004/07/13 22:27:49 jsuttor Exp $ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/* + * @(#)DOMSource.java 1.16 04/07/13 + */ +package javax.xml.transform.dom; + +import javax.xml.transform.Source; + +import org.w3c.dom.Node; + +/** + *

Acts as a holder for a transformation Source tree in the + * form of a Document Object Model (DOM) tree.

+ * + *

Note that XSLT requires namespace support. Attempting to transform a DOM + * that was not contructed with a namespace-aware parser may result in errors. + * Parsers can be made namespace aware by calling + * {@link javax.xml.parsers.DocumentBuilderFactory#setNamespaceAware(boolean awareness)}.

+ * + * @author Jeff Suttor + * @version $Revision: 1.5.14.1.2.2 $, $Date: 2004/07/13 22:27:49 $ + * @see Document Object Model (DOM) Level 2 Specification + */ +public class DOMSource implements Source { + + /** + *

Node to serve as DOM source.

+ */ + private Node node; + + /** + *

The base ID (URL or system ID) from where URLs + * will be resolved.

+ */ + private String systemID; + + /** If {@link javax.xml.transform.TransformerFactory#getFeature} + * returns true when passed this value as an argument, + * the Transformer supports Source input of this type. + */ + public static final String FEATURE = + "http://javax.xml.transform.dom.DOMSource/feature"; + + /** + *

Zero-argument default constructor. If this constructor is used, and + * no DOM source is set using {@link #setNode(Node node)} , then the + * Transformer will + * create an empty source {@link org.w3c.dom.Document} using + * {@link javax.xml.parsers.DocumentBuilder#newDocument()}.

+ * + * @see javax.xml.transform.Transformer#transform(Source xmlSource, Result outputTarget) + */ + public DOMSource() { } + + /** + * Create a new input source with a DOM node. The operation + * will be applied to the subtree rooted at this node. In XSLT, + * a "/" pattern still means the root of the tree (not the subtree), + * and the evaluation of global variables and parameters is done + * from the root node also. + * + * @param n The DOM node that will contain the Source tree. + */ + public DOMSource(Node n) { + setNode(n); + } + + /** + * Create a new input source with a DOM node, and with the + * system ID also passed in as the base URI. + * + * @param node The DOM node that will contain the Source tree. + * @param systemID Specifies the base URI associated with node. + */ + public DOMSource(Node node, String systemID) { + setNode(node); + setSystemId(systemID); + } + + /** + * Set the node that will represents a Source DOM tree. + * + * @param node The node that is to be transformed. + */ + public void setNode(Node node) { + this.node = node; + } + + /** + * Get the node that represents a Source DOM tree. + * + * @return The node that is to be transformed. + */ + public Node getNode() { + return node; + } + + /** + * Set the base ID (URL or system ID) from where URLs + * will be resolved. + * + * @param systemID Base URL for this DOM tree. + */ + public void setSystemId(String systemID) { + this.systemID = systemID; + } + + /** + * Get the base ID (URL or system ID) from where URLs + * will be resolved. + * + * @return Base URL for this DOM tree. + */ + public String getSystemId() { + return this.systemID; + } +} diff --git a/branches/sca-android/android-jdk-classes/src/javax/xml/transform/sax/SAXSource.java b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/sax/SAXSource.java new file mode 100644 index 0000000000..cc09fee0ae --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/javax/xml/transform/sax/SAXSource.java @@ -0,0 +1,195 @@ +// $Id: SAXSource.java,v 1.7.14.1.2.2 2004/07/13 22:27:50 jsuttor Exp $ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +/* + * @(#)SAXSource.java 1.15 04/07/13 + */ +package javax.xml.transform.sax; + +import javax.xml.transform.Source; +//import javax.xml.transform.stream.StreamSource; + +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +/** + *

Acts as an holder for SAX-style Source.

+ * + *

Note that XSLT requires namespace support. Attempting to transform an + * input source that is not + * generated with a namespace-aware parser may result in errors. + * Parsers can be made namespace aware by calling the + * {@link javax.xml.parsers.SAXParserFactory#setNamespaceAware(boolean awareness)} method.

+ * + * @author Jeff Suttor + * @version $Revision: 1.7.14.1.2.2 $, $Date: 2004/07/13 22:27:50 $ + */ +public class SAXSource implements Source { + + /** + * If {@link javax.xml.transform.TransformerFactory#getFeature} + * returns true when passed this value as an argument, + * the Transformer supports Source input of this type. + */ + public static final String FEATURE = + "http://javax.xml.transform.sax.SAXSource/feature"; + + /** + *

Zero-argument default constructor. If this constructor is used, and + * no SAX source is set using + * {@link #setInputSource(InputSource inputSource)} , then the + * Transformer will + * create an empty source {@link org.xml.sax.InputSource} using + * {@link org.xml.sax.InputSource#InputSource() new InputSource()}.

+ * + * @see javax.xml.transform.Transformer#transform(Source xmlSource, Result outputTarget) + */ + public SAXSource() { } + + /** + * Create a SAXSource, using an {@link org.xml.sax.XMLReader} + * and a SAX InputSource. The {@link javax.xml.transform.Transformer} + * or {@link javax.xml.transform.sax.SAXTransformerFactory} will set itself + * to be the reader's {@link org.xml.sax.ContentHandler}, and then will call + * reader.parse(inputSource). + * + * @param reader An XMLReader to be used for the parse. + * @param inputSource A SAX input source reference that must be non-null + * and that will be passed to the reader parse method. + */ + public SAXSource(XMLReader reader, InputSource inputSource) { + this.reader = reader; + this.inputSource = inputSource; + } + + /** + * Create a SAXSource, using a SAX InputSource. + * The {@link javax.xml.transform.Transformer} or + * {@link javax.xml.transform.sax.SAXTransformerFactory} creates a + * reader via {@link org.xml.sax.helpers.XMLReaderFactory} + * (if setXMLReader is not used), sets itself as + * the reader's {@link org.xml.sax.ContentHandler}, and calls + * reader.parse(inputSource). + * + * @param inputSource An input source reference that must be non-null + * and that will be passed to the parse method of the reader. + */ + public SAXSource(InputSource inputSource) { + this.inputSource = inputSource; + } + + /** + * Set the XMLReader to be used for the Source. + * + * @param reader A valid XMLReader or XMLFilter reference. + */ + public void setXMLReader(XMLReader reader) { + this.reader = reader; + } + + /** + * Get the XMLReader to be used for the Source. + * + * @return A valid XMLReader or XMLFilter reference, or null. + */ + public XMLReader getXMLReader() { + return reader; + } + + /** + * Set the SAX InputSource to be used for the Source. + * + * @param inputSource A valid InputSource reference. + */ + public void setInputSource(InputSource inputSource) { + this.inputSource = inputSource; + } + + /** + * Get the SAX InputSource to be used for the Source. + * + * @return A valid InputSource reference, or null. + */ + public InputSource getInputSource() { + return inputSource; + } + + /** + * Set the system identifier for this Source. If an input source + * has already been set, it will set the system ID or that + * input source, otherwise it will create a new input source. + * + *

The system identifier is optional if there is a byte stream + * or a character stream, but it is still useful to provide one, + * since the application can use it to resolve relative URIs + * and can include it in error messages and warnings (the parser + * will attempt to open a connection to the URI only if + * no byte stream or character stream is specified).

+ * + * @param systemId The system identifier as a URI string. + */ + public void setSystemId(String systemId) { + + if (null == inputSource) { + inputSource = new InputSource(systemId); + } else { + inputSource.setSystemId(systemId); + } + } + + /** + *

Get the base ID (URI or system ID) from where URIs + * will be resolved.

+ * + * @return Base URL for the Source, or null. + */ + public String getSystemId() { + + if (inputSource == null) { + return null; + } else { + return inputSource.getSystemId(); + } + } + + /** + * The XMLReader to be used for the source tree input. May be null. + */ + private XMLReader reader; + + /** + *

The SAX InputSource to be used for the source tree input. + * Should not be null.

+ */ + private InputSource inputSource; +/* + *//** + * Attempt to obtain a SAX InputSource object from a Source + * object. + * + * @param source Must be a non-null Source reference. + * + * @return An InputSource, or null if Source can not be converted. + *//* + public static InputSource sourceToInputSource(Source source) { + + if (source instanceof SAXSource) { + return ((SAXSource) source).getInputSource(); + } else if (source instanceof StreamSource) { + StreamSource ss = (StreamSource) source; + InputSource isource = new InputSource(ss.getSystemId()); + + isource.setByteStream(ss.getInputStream()); + isource.setCharacterStream(ss.getReader()); + isource.setPublicId(ss.getPublicId()); + + return isource; + } else { + return null; + } + }*/ +} + diff --git a/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/ContextRegistry.java b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/ContextRegistry.java new file mode 100644 index 0000000000..312c0059db --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/ContextRegistry.java @@ -0,0 +1,55 @@ +package org.apache.tuscany.sca.android; + +import java.util.HashSet; +import java.util.Hashtable; + +import android.content.Context; + +public class ContextRegistry { + + private static Hashtable> contexts = new Hashtable>(); + + public static void registerContext(Context context) { + String packageName = context.getPackageName(); + HashSet packContexts = contexts.get(packageName); + + if (packContexts == null) { + packContexts = new HashSet(); + contexts.put(packageName, packContexts); + + } + + packContexts.add(context); + + } + + public static void unregisterContext(Context context) { + String packageName = context.getPackageName(); + HashSet packContexts = contexts.get(packageName); + + if (packContexts != null) { + packContexts.remove(context); + + if (packContexts.isEmpty()) { + contexts.remove(packageName); + } + + } + + } + + public static Context[] getContexts(String packageName) { + HashSet packageContexts = contexts.get(packageName); + + if (packageContexts == null) { + return new Context[0]; + } + + Context[] ret = new Context[packageContexts.size()]; + packageContexts.toArray(ret); + + return ret; + + } + +} diff --git a/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexResource.java b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexResource.java new file mode 100644 index 0000000000..fb9029547f --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexResource.java @@ -0,0 +1,190 @@ +package org.apache.tuscany.sca.android; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; + +import android.content.Context; + +public class DexResource { + + private URL url; + + private String folder; + + private String file; + + public DexResource(URL url) { + String protocol = url.getProtocol(); + + if (!"dex".equals(protocol)) { + throw new IllegalArgumentException("The URL protocol should be \"dex\""); + } + + String host = url.getHost(); + + if ("".equals(host)) { + throw new IllegalArgumentException("The host should not be empty!"); + } + + String path = url.getPath(); + file = getFile(path); + folder = getFolder(path); + + if (file != null && file.indexOf('/') != -1) { + throw new IllegalArgumentException("The dex URL format should be: dex://[]/[] only"); + } + + this.url = url; + + } + + public static String getFolder(String path) { + String file = path.trim(); + + int firstSlashIndex = file.indexOf('/'); + + if ("".equals(file) || "/".equals(file) || firstSlashIndex == -1 || firstSlashIndex >= file.length() - 1) { + return null; + } + + int secondSlashIndex = file.indexOf("/", firstSlashIndex + 1); + + if (secondSlashIndex == -1 || secondSlashIndex >= file.length() - 1 || firstSlashIndex == secondSlashIndex - 1) { + return null; + } + + return file.substring(firstSlashIndex + 1, secondSlashIndex); + + } + + public static String getFile(String path) { + String file = path.trim(); + + int firstSlashIndex = file.indexOf('/'); + + if ("".equals(file) || "/".equals(file) || firstSlashIndex == -1 || firstSlashIndex >= file.length() - 1) { + return null; + } + + int secondSlashIndex = file.indexOf("/", firstSlashIndex + 1); + + if (secondSlashIndex == -1 || secondSlashIndex >= file.length() - 1 || firstSlashIndex == secondSlashIndex - 1) { + return null; + } + + return file.substring(secondSlashIndex + 1); + + } + + public String getFolderName() { + return folder; + } + + public Context getContext() { + Context[] contexts = ContextRegistry.getContexts(url.getHost()); + + if (contexts.length == 0) { + return null; + } + + return contexts[0]; + + } + + public String getFileName() { + return file; + } + + public boolean isPackage() { + return folder == null; + } + + public boolean isFolder() { + return file == null && folder != null; + } + + public boolean isFile() { + return file != null; + } + + public String getPackageName() { + return url.getHost(); + } + + public URI[] getContentFiles() throws IOException { + + if (isFile()) { + throw new UnsupportedOperationException("Not supported when the resource is a file!"); + } + + String packageName = url.getHost(); + + Context[] contexts = ContextRegistry.getContexts(packageName); + + if (contexts.length == 0) { + throw new IOException("Android context not found!"); + } + + Context context = contexts[0]; + + ArrayList files = new ArrayList(); + StringBuffer className = new StringBuffer(packageName).append(".R"); + + if (isPackage()) { + ClassLoader classLoader = context.getClass().getClassLoader(); + + try { + + for (String folderName : new String[] {"raw", "xml"}) { + Class clazz = classLoader.loadClass(className.toString() + '$' + folderName); + folderName = '/' + folderName + '/'; + Field[] fields = clazz.getFields(); + + for (Field field : fields) { + try { + files.add(new URI("dex://" + packageName + folderName + field.getName())); + } catch (URISyntaxException e) {} + } + + } + + } catch (ClassNotFoundException e) {} + + } else { + + try { + className.append('$').append(folder); + Class clazz = getClass().getClassLoader().loadClass(className.toString()); + String folderName = '/' + clazz.getSimpleName() + '/'; + Field[] fields = clazz.getFields(); + + for (Field field : fields) { + try { + files.add(new URI("dex://" + packageName + folderName + field.getName())); + } catch (URISyntaxException e) {} + } + + } catch (ClassNotFoundException e) { + throw new IOException("Resource not found!"); + } + + } + + + + URI[] ret = new URI[files.size()]; + files.toArray(ret); + + return ret; + + } + + public URL getURL() { + return url; + } + +} diff --git a/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLConnection.java b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLConnection.java new file mode 100644 index 0000000000..af0e93b043 --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLConnection.java @@ -0,0 +1,128 @@ +package org.apache.tuscany.sca.android; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.URL; +import java.net.URLConnection; +import java.net.UnknownServiceException; + +import android.content.Context; + +public class DexURLConnection extends URLConnection { + + private InputStream input; + + protected DexURLConnection(URL url) { + super(url); + setAllowUserInteraction(false); + setUseCaches(false); + setDefaultUseCaches(false); + setConnectTimeout(0); + setReadTimeout(0); + setDoInput(true); + setDoOutput(false); + + } + + public InputStream getInputStream() throws IOException { + + if (input == null) { + connect(); + } + + return input; + + } + + private String guessContentTypeFromInput() { + + if (!connected) { + + try { + connect(); + } catch (IOException e) { + return null; + } + + } + + try { + return guessContentTypeFromStream(input); + } catch (IOException e) { + return null; + } + + } + + @Override + public String getContentType() { + + if (DexResource.getFolder(url.getPath()) == null || DexResource.getFile(url.getPath()) == null) { + return "application/x-dex"; + } + + return guessContentTypeFromInput(); + + } + + public OutputStream getOutputStream() throws IOException { + throw new UnknownServiceException("Output not supported!"); + } + + public void connect() throws IOException { + + if (!connected) { + String host = url.getHost(); + Context[] contexts = ContextRegistry.getContexts(host); + + if (contexts.length == 0) { + throw new IOException("Android context not found!"); + } + + Context context = contexts[0]; + + if ("".equals(host)) { + throw new IOException("not valid host name: \"\""); + } + + String path = url.getPath(); + String file = DexResource.getFile(path); + String folder = DexResource.getFolder(path); + + if (file == null) { + return; + } + + file = file.replace('.', '_'); + + try { + + StringBuffer sb = new StringBuffer(context.getPackageName()); + sb.append('.').append('R').append('$').append(folder); + + Class clazz = getClass().getClassLoader().loadClass(sb.toString()); + Field field = clazz.getDeclaredField(file); + + int id = field.getInt(null); + input = context.getResources().openRawResource(id); + connected = true; + + } catch (ClassNotFoundException e) { + throw new IOException(e.getMessage()); + } catch (SecurityException e) { + throw new IOException(e.getMessage()); + } catch (NoSuchFieldException e) { + throw new IOException(e.getMessage()); + } catch (IllegalArgumentException e) { + throw new IOException(e.getMessage()); + } catch (IllegalAccessException e) { + throw new IOException(e.getMessage()); + } + + } + + } + +} diff --git a/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandler.java b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandler.java new file mode 100644 index 0000000000..a5c1507e0d --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandler.java @@ -0,0 +1,15 @@ +package org.apache.tuscany.sca.android; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +public class DexURLStreamHandler extends URLStreamHandler { + + @Override + protected URLConnection openConnection(URL url) throws IOException { + return new DexURLConnection(url); + } + +} diff --git a/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandlerFactory.java b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandlerFactory.java new file mode 100644 index 0000000000..5bb53dcd2e --- /dev/null +++ b/branches/sca-android/android-jdk-classes/src/org/apache/tuscany/sca/android/DexURLStreamHandlerFactory.java @@ -0,0 +1,33 @@ +package org.apache.tuscany.sca.android; + +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; + +public class DexURLStreamHandlerFactory implements URLStreamHandlerFactory { + + private static DexURLStreamHandlerFactory instance; + + public static DexURLStreamHandlerFactory getInstance() { + + if (instance == null) { + instance = new DexURLStreamHandlerFactory(); + } + + return instance; + + } + + public DexURLStreamHandlerFactory() {} + + public URLStreamHandler createURLStreamHandler(String protocol) { + URLStreamHandler urlStreamHandler = null; + + if ("dex".equals(protocol)) { + urlStreamHandler = new DexURLStreamHandler(); + } + + return urlStreamHandler; + + } + +} diff --git a/branches/sca-android/binding-jsonrpc/.classpath b/branches/sca-android/binding-jsonrpc/.classpath new file mode 100644 index 0000000000..6403d2bc4b --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/.classpath @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/binding-jsonrpc/.project b/branches/sca-android/binding-jsonrpc/.project new file mode 100644 index 0000000000..855e78deec --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/.project @@ -0,0 +1,51 @@ + + tuscany-binding-jsonrpc + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-core + tuscany-core-spi + tuscany-sca-api + tuscany-contribution + tuscany-contribution-java + tuscany-interface-java + tuscany-databinding + tuscany-databinding-json + tuscany-host-embedded + tuscany-definitions-xml + tuscany-policy-xml + tuscany-assembly-xml + tuscany-contribution-namespace + tuscany-binding-sca + tuscany-contribution-impl + tuscany-contribution-xml + tuscany-contribution-resource + tuscany-node + tuscany-domain + tuscany-domain-api + tuscany-node-api + tuscany-binding-sca-xml + tuscany-core-databinding + tuscany-databinding-jaxb + tuscany-interface-java-xml + tuscany-interface-java-jaxws + tuscany-assembly-xsd + tuscany-host-http + tuscany-host-jetty + tuscany-implementation-java-runtime + tuscany-implementation-java + tuscany-implementation-java-xml + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/binding-jsonrpc/DISCLAIMER b/branches/sca-android/binding-jsonrpc/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/binding-jsonrpc/LICENSE b/branches/sca-android/binding-jsonrpc/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/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/branches/sca-android/binding-jsonrpc/NOTICE b/branches/sca-android/binding-jsonrpc/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/binding-jsonrpc/pom.xml b/branches/sca-android/binding-jsonrpc/pom.xml new file mode 100644 index 0000000000..39fcbada89 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/pom.xml @@ -0,0 +1,144 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + + tuscany-binding-jsonrpc + Apache Tuscany SCA JSON-RPC Binding Extension + + + + com.metaparadigm + json-rpc + 1.0 + compile + + + + org.apache.tuscany.sca + tuscany-assembly + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-core-spi + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-core + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-databinding + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-databinding-json + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-host-http + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-host-jetty + 2.0-incubating-SNAPSHOT + test + + + + javax.servlet + servlet-api + 2.4 + provided + + + + commons-logging + commons-logging + 1.1 + + + commons-logging + commons-logging + + + javax.servlet + servlet-api + + + + + + + + org.apache.tuscany.sca + tuscany-host-embedded + 2.0-incubating-SNAPSHOT + test + + + + org.apache.tuscany.sca + tuscany-implementation-java-runtime + 2.0-incubating-SNAPSHOT + test + + + + junit + junit + 4.2 + test + + + + httpunit + httpunit + 1.6.1 + test + + + + + diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCBinding.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCBinding.java new file mode 100644 index 0000000000..c7b6caf466 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCBinding.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.jsonrpc; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.OptimizableBinding; + +/** + * A model for the JSONRPC binding. + * + * @version $Rev: 589538 $ $Date: 2007-10-29 00:15:47 -0800 (Mon, 29 Oct 2007) $ + */ +public class JSONRPCBinding implements OptimizableBinding { + private String name; + private String uri; + + public String getName() { + return name; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isUnresolved() { + // The binding is always resolved + return false; + } + + public void setUnresolved(boolean unresolved) { + // The binding is always resolved + } + + //FIXME Temporary to get access to the target binding information + // To be removed when the distributed domain supports wiring of other + // bindings than the SCA binding + private Binding targetBinding; + private Component targetComponent; + private ComponentService targetComponentService; + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public Binding getTargetBinding() { + return targetBinding; + } + + public void setTargetBinding(Binding binding) { + this.targetBinding = binding; + } + + public Component getTargetComponent() { + return targetComponent; + } + + public void setTargetComponent(Component component) { + this.targetComponent = component; + } + + public ComponentService getTargetComponentService() { + return targetComponentService; + } + + public void setTargetComponentService(ComponentService service) { + this.targetComponentService = service; + } + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceServlet.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceServlet.java new file mode 100644 index 0000000000..afef327291 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceServlet.java @@ -0,0 +1,284 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.binding.jsonrpc; + +import java.io.BufferedReader; +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import javax.servlet.ServletConfig; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.json.JSONArray; +import org.json.JSONObject; +import org.osoa.sca.ServiceRuntimeException; + +import com.metaparadigm.jsonrpc.JSONRPCBridge; +import com.metaparadigm.jsonrpc.JSONRPCServlet; + +/** + * Servlet that handles JSON-RPC requests invoking SCA services. + * + * There is an instance of this Servlet for each + */ +public class JSONRPCServiceServlet extends JSONRPCServlet { + private static final long serialVersionUID = 1L; + + transient Binding binding; + transient String serviceName; + transient Object serviceInstance; + transient RuntimeComponentService componentService; + transient InterfaceContract serviceContract; + transient Class serviceInterface; + + public JSONRPCServiceServlet(Binding binding, + RuntimeComponentService componentService, + InterfaceContract serviceContract, + Class serviceInterface, + Object serviceInstance) { + this.binding = binding; + this.serviceName = binding.getName(); + this.componentService = componentService; + this.serviceContract = serviceContract; + this.serviceInterface = serviceInterface; + this.serviceInstance = serviceInstance; + } + + /** + * Override to do nothing as the JSONRPCServlet is setup by the + * service method in this class. + */ + @Override + public void init(ServletConfig config) { + } + + @Override + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { + if ("smd".equals(request.getQueryString())) { + handleSMDRequest(request, response); + } else { + try { + handleServiceRequest(request, response); + } finally { + HttpSession session = request.getSession(false); + if (session != null) { + session.removeAttribute("JSONRPCBridge"); + } + } + } + } + + private void handleServiceRequest(HttpServletRequest request, HttpServletResponse response) + throws IOException { + // Encode using UTF-8, although We are actually ASCII clean as + // all unicode data is JSON escaped using backslash u. This is + // less data efficient for foreign character sets but it is + // needed to support naughty browsers such as Konqueror and Safari + // which do not honour the charset set in the response + response.setContentType("text/plain;charset=utf-8"); + OutputStream out = response.getOutputStream(); + + // Decode using the charset in the request if it exists otherwise + // use UTF-8 as this is what all browser implementations use. + // The JSON-RPC-Java JavaScript client is ASCII clean so it + // although here we can correctly handle data from other clients + // that do not escape non ASCII data + String charset = request.getCharacterEncoding(); + if (charset == null) { + charset = "UTF-8"; + } + BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), charset)); + + // Read the request + CharArrayWriter data = new CharArrayWriter(); + char buf[] = new char[4096]; + int ret; + while ((ret = in.read(buf, 0, 4096)) != -1) { + data.write(buf, 0, ret); + } + + JSONObject jsonReq = null; + String method = null; + try { + jsonReq = new JSONObject(data.toString()); + method = jsonReq.getString("method"); + } catch (Exception e) { + //FIXME Exceptions are not handled correctly here + // They should be reported to the client JavaScript as proper + // JavaScript exceptions. + throw new RuntimeException("Unable to parse request", e); + } + + + // check if it's a system request + // or a method invocation + byte[] bout; + if (method.startsWith("system.")) { + bout = handleJSONRPCSystemInvocation(request, response, data.toString()); + } else { + bout = handleJSONRPCMethodInvocation(request, response, jsonReq); + } + + // Send response to client + out.write(bout); + out.flush(); + out.close(); + } + + /** + * handles requests for the SMD descriptor for a service + */ + protected void handleSMDRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, + UnsupportedEncodingException { + String serviceUrl = request.getRequestURL().toString(); + String smd = JavaToSmd.interfaceToSmd(serviceInterface, serviceUrl); + + response.setContentType("text/plain;charset=utf-8"); + OutputStream out = response.getOutputStream(); + byte[] bout = smd.getBytes("UTF-8"); + + out.write(bout); + out.flush(); + out.close(); + } + + protected byte[] handleJSONRPCSystemInvocation(HttpServletRequest request, HttpServletResponse response, String requestData) throws IOException, + UnsupportedEncodingException { + /* + * Create a new bridge for every request to avoid all the problems with + * JSON-RPC-Java storing the bridge in the session + */ + HttpSession session = request.getSession(); + + JSONRPCBridge jsonrpcBridge = new JSONRPCBridge(); + jsonrpcBridge.registerObject("Service", serviceInstance, serviceInterface); + session.setAttribute("JSONRPCBridge", jsonrpcBridge); + + org.json.JSONObject jsonReq = null; + com.metaparadigm.jsonrpc.JSONRPCResult jsonResp = null; + /* try { + jsonReq = new org.json.JSONObject(requestData); + } catch (java.text.ParseException e) { + throw new RuntimeException("Unable to parse request", e); + } + + String method = jsonReq.getString("method"); + if ((method != null) && (method.indexOf('.') < 0)) { + jsonReq.putOpt("method", "Service" + "." + method); + } + + // invoke the request + jsonResp = jsonrpcBridge.call(new Object[] {request}, jsonReq); + + return jsonResp.toString().getBytes("UTF-8");*/ + throw new UnsupportedOperationException("not implemented in Android!"); + } + + protected byte[] handleJSONRPCMethodInvocation(HttpServletRequest request, HttpServletResponse response, JSONObject jsonReq) throws IOException, + UnsupportedEncodingException { + + String method = null; + Object[] args = null; + Object id = null; + try { + // Extract the method + method = jsonReq.getString("method"); + if ((method != null) && (method.indexOf('.') < 0)) { + jsonReq.putOpt("method", "Service" + "." + method); + } + + // Extract the arguments + JSONArray array = jsonReq.getJSONArray("params"); + args = new Object[array.length()]; + for (int i = 0; i < args.length; i++) { + args[i] = array.get(i); + } + id = jsonReq.get("id"); + + } catch (Exception e) { + throw new RuntimeException("Unable to find json method name", e); + } + + // invoke the request + RuntimeWire wire = componentService.getRuntimeWire(binding, serviceContract); + Operation jsonOperation = findOperation(method); + Object result = null; + JSONObject jsonResponse = new JSONObject(); + try { + result = wire.invoke(jsonOperation, args); + try { + jsonResponse.put("result", result); + jsonResponse.putOpt("id", id); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } catch (InvocationTargetException e) { + try { + jsonResponse.put("error", e.getCause()); + jsonResponse.putOpt("id", id); + } catch (Exception e1) { + throw new ServiceRuntimeException(e); + } + } catch(RuntimeException e) { + e.printStackTrace(); + throw e; + } + + //get response to send to client + return jsonResponse.toString().getBytes("UTF-8"); + } + + /** + * Find the operation from the component service contract + * @param componentService + * @param method + * @return + */ + private Operation findOperation(String method) { + if (method.contains(".")) { + method = method.substring(method.lastIndexOf(".") + 1); + } + + List operations = serviceContract.getInterface().getOperations(); + //componentService.getBindingProvider(binding).getBindingInterfaceContract().getInterface().getOperations(); + + + Operation result = null; + for (Operation o : operations) { + if (o.getName().equalsIgnoreCase(method)) { + result = o; + break; + } + } + + return result; + } +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JavaToSmd.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JavaToSmd.java new file mode 100644 index 0000000000..4bac565fdd --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/JavaToSmd.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.apache.tuscany.sca.binding.jsonrpc; + +import java.lang.reflect.Method; + +/** + * Utility class to create a Simple Method Description (SMD) descriptor + * from a Java class. See http://dojo.jot.com/SMD. + * + * TODO: Change to work from the Tuscany Interface instead of a Java class + * + * @version $Rev: 639240 $ $Date: 2008-03-20 02:59:23 -0800 (Thu, 20 Mar 2008) $ + */ +public class JavaToSmd { + + public static String interfaceToSmd(Class klazz, String serviceUrl) { + String name = klazz.getSimpleName(); + Method methods[] = klazz.getMethods(); + + StringBuffer smdSb = new StringBuffer(); + smdSb.append("{\"SMDVersion\":\".1\",\"objectName\":\"" + name + "\",\"serviceType\":\"JSON-RPC\",\"serviceURL\":\""+ serviceUrl + "\",\"methods\":["); + for (int i = 0; i < methods.length; i++) { + if (i != 0) smdSb.append(","); + Class params[] = methods[i].getParameterTypes(); + smdSb.append("{\"name\":\""+methods[i].getName() + "\",\"parameters\":["); + for (int j = 0; j < params.length; j++) { + if (j != 0) smdSb.append(","); + // right now Dojo doesn't look at the type value, so we'll default it to STRING + // also, since we can't introspect the method parameter names we'll just create an incrementing parameter name + smdSb.append("{\"name\":\"param" + j + "\",\"type\":\"STRING\"}"); + } + smdSb.append("]}"); + } + smdSb.append("]}"); + + return smdSb.toString(); + } + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/ScaDomainScriptServlet.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/ScaDomainScriptServlet.java new file mode 100644 index 0000000000..4110e7e9d3 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/ScaDomainScriptServlet.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.binding.jsonrpc; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Servlet to handle requests for the scaDomain.js script. + * + * This script wrappers the JSON-RPC-Java jsonrpc.js script + * adding in at the bottom the JavaScript to create and initialize + * the variables representing the SCA services. + * + * @version $Rev: 589490 $ $Date: 2007-10-28 20:37:49 -0800 (Sun, 28 Oct 2007) $ + */ +public class ScaDomainScriptServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + protected transient List serviceNames; + + public ScaDomainScriptServlet() { + serviceNames = new ArrayList(); + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + + ServletOutputStream os = response.getOutputStream(); + + os.println(); + os.println("/* Apache Tuscany scaDomain.js Header */"); + os.println(); + + writeJSONRPCJavaScript(os); + writeScaDomainCode(os, request.getServletPath()); + } + + /** + * Creates a JavaScript variable within the scaDomain script for each SCA service and + * initializes its value with the JSON-RPC client to invoke the serverside service. + */ + protected void writeScaDomainCode(ServletOutputStream out, String path) throws IOException { + out.println(); + out.println("/* Apache Tuscany scaDomain.js Footer */"); + out.println(); + out.println("function scaDomain() {}"); + + // remove the leading slash '/' character + path = path.substring(1); + + for (String serviceName : serviceNames) { + out.println(); + + // A slight hack to make the service function available with a variable named 'serviceName' + // to do that the JSONRpcClient is added to the scaDomain and then the service function is got from that + out.println("scaDomain." + serviceName + " = " + "new JSONRpcClient(\"" + serviceName + "\");"); + out.println(serviceName + " = scaDomain." + serviceName + ".Service;"); + } + + out.println(); + out.println("/** End of Apache Tuscany scaDomain.js */"); + out.println(); + } + + /** + * Reads the jsonrpc.js script from the classpath and adds its contents to the output stream. + */ + protected void writeJSONRPCJavaScript(ServletOutputStream os) throws IOException { + URL url = getClass().getResource("jsonrpc.js"); + InputStream is = url.openStream(); + int i; + while ((i = is.read()) != -1) { + os.write(i); + } + } + + public void addService(String serviceName) { + serviceNames.add(serviceName); + } + + public void removeService(String serviceName) { + serviceNames.remove(serviceName); + } + + public List getServiceNames() { + return serviceNames; + } + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.java new file mode 100644 index 0000000000..de8278ced9 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingInvoker.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.binding.jsonrpc.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + +/** + * Invoker for the JSONRPC Binding + * + * @version $Rev: 587029 $ $Date: 2007-10-22 00:29:29 -0800 (Mon, 22 Oct 2007) $ + */ +public class JSONRPCBindingInvoker implements Invoker { + Operation operation; + String uri; + + public JSONRPCBindingInvoker(Operation operation, String uri) { + this.operation = operation; + this.uri = uri; + } + + public Message invoke(Message msg) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java new file mode 100644 index 0000000000..f14016eae4 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCBindingProviderFactory.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.jsonrpc.provider; + +import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.host.http.ServletHostExtensionPoint; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * JSON-RPC Provider Factory + * + * @version $Rev: 638859 $ $Date: 2008-03-19 07:09:39 -0800 (Wed, 19 Mar 2008) $ + */ +public class JSONRPCBindingProviderFactory implements BindingProviderFactory { + + private ServletHost servletHost; + + public JSONRPCBindingProviderFactory(ExtensionPointRegistry extensionPoints) { + ServletHostExtensionPoint servletHosts = extensionPoints.getExtensionPoint(ServletHostExtensionPoint.class); + this.servletHost = servletHosts.getServletHosts().get(0); + } + + public ReferenceBindingProvider createReferenceBindingProvider(RuntimeComponent component, + RuntimeComponentReference reference, + JSONRPCBinding binding) { + + return new JSONRPCReferenceBindingProvider(component, reference, binding); + } + + public ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, + JSONRPCBinding binding) { + return new JSONRPCServiceBindingProvider(component, service, binding, servletHost); + } + + public Class getModelType() { + return JSONRPCBinding.class; + } + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.java new file mode 100644 index 0000000000..cf04398c16 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCReferenceBindingProvider.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.binding.jsonrpc.provider; + +import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; + +/** + * Implementation of the JSONRPC Binding Provider for References + * + * @version $Rev: 587030 $ $Date: 2007-10-22 00:30:56 -0800 (Mon, 22 Oct 2007) $ + */ +public class JSONRPCReferenceBindingProvider implements ReferenceBindingProvider { + + private RuntimeComponentReference reference; + private JSONRPCBinding binding; + + public JSONRPCReferenceBindingProvider(RuntimeComponent component, + RuntimeComponentReference reference, + JSONRPCBinding binding) { + this.reference = reference; + this.binding = binding; + + } + + public InterfaceContract getBindingInterfaceContract() { + return reference.getInterfaceContract(); + } + + public Invoker createInvoker(Operation operation) { + return new JSONRPCBindingInvoker(operation, binding.getURI()); + } + + public void start() { + // TODO Auto-generated method stub + + } + + public void stop() { + // TODO Auto-generated method stub + + } + + public boolean supportsOneWayInvocation() { + return false; + } + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java new file mode 100644 index 0000000000..cb08ef15e2 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/java/org/apache/tuscany/sca/binding/jsonrpc/provider/JSONRPCServiceBindingProvider.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.binding.jsonrpc.provider; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding; +import org.apache.tuscany.sca.binding.jsonrpc.JSONRPCServiceServlet; +import org.apache.tuscany.sca.binding.jsonrpc.ScaDomainScriptServlet; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; +import org.apache.tuscany.sca.databinding.json.JSONDataBinding; +import org.apache.tuscany.sca.host.http.ServletHost; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Implementation of the JSONRPC Binding Provider for Services + * + * @version $Rev: 639240 $ $Date: 2008-03-20 02:59:23 -0800 (Thu, 20 Mar 2008) $ + */ +public class JSONRPCServiceBindingProvider implements ServiceBindingProvider { + + // Path to the scaDomain.js script + // Note: this is the same as the Ajax binding to keep the client code + // the same for clients using either the ajax or jsonrpc binding + private static final String SCA_DOMAIN_SCRIPT = "/SCADomain/scaDomain.js"; + + private RuntimeComponent component; + private RuntimeComponentService service; + private InterfaceContract serviceContract; + private JSONRPCBinding binding; + private ServletHost servletHost; + private List servletMappings = new ArrayList(); + private String domainScriptMapping; + + public JSONRPCServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, + JSONRPCBinding binding, + ServletHost servletHost) { + this.component = component; + this.service = service; + this.binding = binding; + this.servletHost = servletHost; + + //clone the service contract to avoid databinding issues + try { + this.serviceContract = (InterfaceContract)service.getInterfaceContract().clone(); + } catch(CloneNotSupportedException e) { + this.serviceContract = service.getInterfaceContract(); + } + + setDataBinding(serviceContract.getInterface()); + } + + public InterfaceContract getBindingInterfaceContract() { + return service.getInterfaceContract(); + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public void start() { + // Set default databinding to json + serviceContract.getInterface().setDefaultDataBinding(JSONDataBinding.NAME); + + // Determine the service business interface + Class serviceInterface = getTargetJavaClass(serviceContract.getInterface()); + + // Create a Java proxy to the target service + Object proxy = component.getComponentContext().createSelfReference(serviceInterface, service).getService(); + + // Create and register a Servlet for this service + JSONRPCServiceServlet serviceServlet = + new JSONRPCServiceServlet(binding, service, serviceContract, serviceInterface, proxy); + String mapping = binding.getURI(); + if (!mapping.endsWith("/")) { + mapping += "/"; + } + if (!mapping.endsWith("*")) { + mapping += "*"; + } + + servletHost.addServletMapping(mapping, serviceServlet); + servletMappings.add(mapping); + servletHost.addServletMapping(binding.getURI(), serviceServlet); + servletMappings.add(binding.getURI()); + + // Save the actual binding URI + binding.setURI(servletHost.getURLMapping(binding.getURI()).toString()); + + // Register service to scaDomain.js + int port; + URI uri = URI.create(binding.getURI()); + port = uri.getPort(); + if (port == -1) { + port = servletHost.getDefaultPort(); + } + + // get the ScaDomainScriptServlet, if it doesn't yet exist create one + // this uses removeServletMapping / addServletMapping as there is no getServletMapping facility + domainScriptMapping = URI.create("http://localhost:" + port + SCA_DOMAIN_SCRIPT).toString(); + ScaDomainScriptServlet scaDomainServlet = + (ScaDomainScriptServlet)servletHost.getServletMapping(domainScriptMapping); + if (scaDomainServlet == null) { + scaDomainServlet = new ScaDomainScriptServlet(); + servletHost.addServletMapping(domainScriptMapping, scaDomainServlet); + } + + // Add this service to the SCA Domain Script Servlet + scaDomainServlet.addService(binding.getName()); + } + + public void stop() { + + // Remove the Servlet mappings we've added + for (String mapping: servletMappings) { + servletHost.removeServletMapping(mapping); + } + + // Unregister the service from the SCA Domain Script Servlet + ScaDomainScriptServlet scaDomainServlet = (ScaDomainScriptServlet) servletHost.getServletMapping(domainScriptMapping); + if (scaDomainServlet != null) { + scaDomainServlet.removeService(binding.getName()); + + // Remove the Servlet if there's no more registered services + if (scaDomainServlet.getServiceNames().isEmpty()) { + servletHost.removeServletMapping(domainScriptMapping); + } + } + + } + + private Class getTargetJavaClass(Interface targetInterface) { + // TODO: right now assume that the target is always a Java + // Implementation. Need to figure out how to generate Java + // Interface in cases where the target is not a Java Implementation + return ((JavaInterface)targetInterface).getJavaClass(); + } + + private void setDataBinding(Interface interfaze) { + List operations = interfaze.getOperations(); + for (Operation operation : operations) { + operation.setDataBinding(JSONDataBinding.NAME); + DataType> inputType = operation.getInputType(); + if (inputType != null) { + List logical = inputType.getLogical(); + for (DataType inArg : logical) { + if (!SimpleJavaDataBinding.NAME.equals(inArg.getDataBinding())) { + inArg.setDataBinding(JSONDataBinding.NAME); + } + } + } + DataType outputType = operation.getOutputType(); + if (outputType != null) { + if (!SimpleJavaDataBinding.NAME.equals(outputType.getDataBinding())) { + outputType.setDataBinding(JSONDataBinding.NAME); + } + } + } + } + + +} diff --git a/branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..3adbec0f97 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -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. + +# Implementation class for the artifact processor extension +org.apache.tuscany.sca.assembly.xml.DefaultBeanModelProcessor;qname=http://tuscany.apache.org/xmlns/sca/1.0#binding.jsonrpc,model=org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding diff --git a/branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory b/branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory new file mode 100644 index 0000000000..4767358e7a --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.BindingProviderFactory @@ -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. + +# Implementation class for the binding extension +org.apache.tuscany.sca.binding.jsonrpc.provider.JSONRPCBindingProviderFactory;model=org.apache.tuscany.sca.binding.jsonrpc.JSONRPCBinding diff --git a/branches/sca-android/binding-jsonrpc/src/main/resources/org/apache/tuscany/sca/binding/jsonrpc/jsonrpc.js b/branches/sca-android/binding-jsonrpc/src/main/resources/org/apache/tuscany/sca/binding/jsonrpc/jsonrpc.js new file mode 100644 index 0000000000..8eb477c2e5 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/main/resources/org/apache/tuscany/sca/binding/jsonrpc/jsonrpc.js @@ -0,0 +1,493 @@ +/* + * JSON-RPC JavaScript client + * + * $Id: jsonrpc.js,v 1.36.2.3 2006/03/08 15:09:37 mclark Exp $ + * + * Copyright (c) 2003-2004 Jan-Klaas Kollhof + * Copyright (c) 2005 Michael Clark, Metaparadigm Pte Ltd + * + * This code is based on Jan-Klaas' JavaScript o lait library (jsolait). + * + * 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. + * + */ + +/* + * Modifications for Apache Tuscany: + * - JSONRpcClient_createMethod changed so callback is last arg + */ + +/* escape a character */ + +escapeJSONChar = +function escapeJSONChar(c) +{ + if(c == "\"" || c == "\\") return "\\" + c; + else if (c == "\b") return "\\b"; + else if (c == "\f") return "\\f"; + else if (c == "\n") return "\\n"; + else if (c == "\r") return "\\r"; + else if (c == "\t") return "\\t"; + var hex = c.charCodeAt(0).toString(16); + if(hex.length == 1) return "\\u000" + hex; + else if(hex.length == 2) return "\\u00" + hex; + else if(hex.length == 3) return "\\u0" + hex; + else return "\\u" + hex; +}; + + +/* encode a string into JSON format */ + +escapeJSONString = +function escapeJSONString(s) +{ + /* The following should suffice but Safari's regex is b0rken + (doesn't support callback substitutions) + return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, + escapeJSONChar) + "\""; + */ + + /* Rather inefficient way to do it */ + var parts = s.split(""); + for(var i=0; i < parts.length; i++) { + var c =parts[i]; + if(c == '"' || + c == '\\' || + c.charCodeAt(0) < 32 || + c.charCodeAt(0) >= 128) + parts[i] = escapeJSONChar(parts[i]); + } + return "\"" + parts.join("") + "\""; +}; + + +/* Marshall objects to JSON format */ + +toJSON = function toJSON(o) +{ + if(o == null) { + return "null"; + } else if(o.constructor == String) { + return escapeJSONString(o); + } else if(o.constructor == Number) { + return o.toString(); + } else if(o.constructor == Boolean) { + return o.toString(); + } else if(o.constructor == Date) { + return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}'; + } else if(o.constructor == Array) { + var v = []; + for(var i = 0; i < o.length; i++) v.push(toJSON(o[i])); + return "[" + v.join(", ") + "]"; + } else { + var v = []; + for(attr in o) { + if(o[attr] == null) v.push("\"" + attr + "\": null"); + else if(typeof o[attr] == "function"); /* skip */ + else v.push(escapeJSONString(attr) + ": " + toJSON(o[attr])); + } + return "{" + v.join(", ") + "}"; + } +}; + + +/* JSONRpcClient constructor */ + +JSONRpcClient = +function JSONRpcClient_ctor(serverURL, user, pass, objectID) +{ + this.serverURL = serverURL; + this.user = user; + this.pass = pass; + this.objectID = objectID; + + /* Add standard methods */ + if(this.objectID) { + this._addMethods(["listMethods"]); + var req = this._makeRequest("listMethods", []); + } else { + this._addMethods(["system.listMethods"]); + var req = this._makeRequest("system.listMethods", []); + } + var m = this._sendRequest(req); + this._addMethods(m); +}; + + +/* JSONRpcCLient.Exception */ + +JSONRpcClient.Exception = +function JSONRpcClient_Exception_ctor(code, message, javaStack) +{ + this.code = code; + var name; + if(javaStack) { + this.javaStack = javaStack; + var m = javaStack.match(/^([^:]*)/); + if(m) name = m[0]; + } + if(name) this.name = name; + else this.name = "JSONRpcClientException"; + this.message = message; +}; + +JSONRpcClient.Exception.CODE_REMOTE_EXCEPTION = 490; +JSONRpcClient.Exception.CODE_ERR_CLIENT = 550; +JSONRpcClient.Exception.CODE_ERR_PARSE = 590; +JSONRpcClient.Exception.CODE_ERR_NOMETHOD = 591; +JSONRpcClient.Exception.CODE_ERR_UNMARSHALL = 592; +JSONRpcClient.Exception.CODE_ERR_MARSHALL = 593; + +JSONRpcClient.Exception.prototype = new Error(); + +JSONRpcClient.Exception.prototype.toString = +function JSONRpcClient_Exception_toString(code, msg) +{ + return this.name + ": " + this.message; +}; + + +/* Default top level exception handler */ + +JSONRpcClient.default_ex_handler = +function JSONRpcClient_default_ex_handler(e) { alert(e); }; + + +/* Client settable variables */ + +JSONRpcClient.toplevel_ex_handler = JSONRpcClient.default_ex_handler; +JSONRpcClient.profile_async = false; +JSONRpcClient.max_req_active = 1; +JSONRpcClient.requestId = 1; + + +/* JSONRpcClient implementation */ + +JSONRpcClient.prototype._createMethod = +function JSONRpcClient_createMethod(methodName) +{ + var fn=function() + { + var args = []; + var callback = null; + for(var i=0;i 0) { + var res = JSONRpcClient.async_responses.shift(); + if(res.canceled) continue; + if(res.profile) res.profile.dispatch = new Date(); + try { + res.cb(res.result, res.ex, res.profile); + } catch(e) { + JSONRpcClient.toplevel_ex_handler(e); + } + } + + while(JSONRpcClient.async_requests.length > 0 && + JSONRpcClient.num_req_active < JSONRpcClient.max_req_active) { + var req = JSONRpcClient.async_requests.shift(); + if(req.canceled) continue; + req.client._sendRequest.call(req.client, req); + } +}; + +JSONRpcClient.kick_async = +function JSONRpcClient_kick_async() +{ + if(JSONRpcClient.async_timeout == null) + JSONRpcClient.async_timeout = + setTimeout(JSONRpcClient._async_handler, 0); +}; + +JSONRpcClient.cancelRequest = +function JSONRpcClient_cancelRequest(requestId) +{ + /* If it is in flight then mark it as canceled in the inflight map + and the XMLHttpRequest callback will discard the reply. */ + if(JSONRpcClient.async_inflight[requestId]) { + JSONRpcClient.async_inflight[requestId].canceled = true; + return true; + } + + /* If its not in flight yet then we can just mark it as canceled in + the the request queue and it will get discarded before being sent. */ + for(var i in JSONRpcClient.async_requests) { + if(JSONRpcClient.async_requests[i].requestId == requestId) { + JSONRpcClient.async_requests[i].canceled = true; + return true; + } + } + + /* It may have returned from the network and be waiting for its callback + to be dispatched, so mark it as canceled in the response queue + and the response will get discarded before calling the callback. */ + for(var i in JSONRpcClient.async_responses) { + if(JSONRpcClient.async_responses[i].requestId == requestId) { + JSONRpcClient.async_responses[i].canceled = true; + return true; + } + } + + return false; +}; + +JSONRpcClient.prototype._makeRequest = +function JSONRpcClient_makeRequest(methodName, args, cb) +{ + var req = {}; + req.client = this; + req.requestId = JSONRpcClient.requestId++; + + var obj = {}; + obj.id = req.requestId; + if (this.objectID) + obj.method = ".obj#" + this.objectID + "." + methodName; + else + obj.method = methodName; + obj.params = args; + + if (cb) req.cb = cb; + if (JSONRpcClient.profile_async) + req.profile = { "submit": new Date() }; + req.data = toJSON(obj); + + return req; +}; + +JSONRpcClient.prototype._sendRequest = +function JSONRpcClient_sendRequest(req) +{ + if(req.profile) req.profile.start = new Date(); + + /* Get free http object from the pool */ + var http = JSONRpcClient.poolGetHTTPRequest(); + JSONRpcClient.num_req_active++; + + /* Send the request */ + if (typeof(this.user) == "undefined") { + http.open("POST", this.serverURL, (req.cb != null)); + } else { + http.open("POST", this.serverURL, (req.cb != null), this.user, this.pass); + } + + /* setRequestHeader is missing in Opera 8 Beta */ + try { http.setRequestHeader("Content-type", "text/plain"); } catch(e) {} + + /* Construct call back if we have one */ + if(req.cb) { + var self = this; + http.onreadystatechange = function() { + if(http.readyState == 4) { + http.onreadystatechange = function () {}; + var res = { "cb": req.cb, "result": null, "ex": null}; + if (req.profile) { + res.profile = req.profile; + res.profile.end = new Date(); + } + try { res.result = self._handleResponse(http); } + catch(e) { res.ex = e; } + if(!JSONRpcClient.async_inflight[req.requestId].canceled) + JSONRpcClient.async_responses.push(res); + delete JSONRpcClient.async_inflight[req.requestId]; + JSONRpcClient.kick_async(); + } + }; + } else { + http.onreadystatechange = function() {}; + } + + JSONRpcClient.async_inflight[req.requestId] = req; + + try { + http.send(req.data); + } catch(e) { + JSONRpcClient.poolReturnHTTPRequest(http); + JSONRpcClient.num_req_active--; + throw new JSONRpcClient.Exception + (JSONRpcClient.Exception.CODE_ERR_CLIENT, "Connection failed"); + } + + if(!req.cb) return this._handleResponse(http); +}; + +JSONRpcClient.prototype._handleResponse = +function JSONRpcClient_handleResponse(http) +{ + /* Get the charset */ + if(!this.charset) { + this.charset = JSONRpcClient._getCharsetFromHeaders(http); + } + + /* Get request results */ + var status, statusText, data; + try { + status = http.status; + statusText = http.statusText; + data = http.responseText; + } catch(e) { + JSONRpcClient.poolReturnHTTPRequest(http); + JSONRpcClient.num_req_active--; + JSONRpcClient.kick_async(); + throw new JSONRpcClient.Exception + (JSONRpcClient.Exception.CODE_ERR_CLIENT, "Connection failed"); + } + + /* Return http object to the pool; */ + JSONRpcClient.poolReturnHTTPRequest(http); + JSONRpcClient.num_req_active--; + + /* Unmarshall the response */ + if(status != 200) { + throw new JSONRpcClient.Exception(status, statusText); + } + var obj; + try { + eval("obj = " + data); + } catch(e) { + throw new JSONRpcClient.Exception(550, "error parsing result"); + } + if(obj.error) + throw new JSONRpcClient.Exception(obj.error.code, obj.error.msg, + obj.error.trace); + var res = obj.result; + + /* Handle CallableProxy */ + if(res && res.objectID && res.JSONRPCType == "CallableReference") + return new JSONRpcClient(this.serverURL, this.user, + this.pass, res.objectID); + + return res; +}; + + +/* XMLHttpRequest wrapper code */ + +/* XMLHttpRequest pool globals */ +JSONRpcClient.http_spare = []; +JSONRpcClient.http_max_spare = 8; + +JSONRpcClient.poolGetHTTPRequest = +function JSONRpcClient_pool_getHTTPRequest() +{ + if(JSONRpcClient.http_spare.length > 0) { + return JSONRpcClient.http_spare.pop(); + } + return JSONRpcClient.getHTTPRequest(); +}; + +JSONRpcClient.poolReturnHTTPRequest = +function JSONRpcClient_poolReturnHTTPRequest(http) +{ + if(JSONRpcClient.http_spare.length >= JSONRpcClient.http_max_spare) + delete http; + else + JSONRpcClient.http_spare.push(http); +}; + +JSONRpcClient.msxmlNames = [ "MSXML2.XMLHTTP.5.0", + "MSXML2.XMLHTTP.4.0", + "MSXML2.XMLHTTP.3.0", + "MSXML2.XMLHTTP", + "Microsoft.XMLHTTP" ]; + +JSONRpcClient.getHTTPRequest = +function JSONRpcClient_getHTTPRequest() +{ + /* Mozilla XMLHttpRequest */ + try { + JSONRpcClient.httpObjectName = "XMLHttpRequest"; + return new XMLHttpRequest(); + } catch(e) {} + + /* Microsoft MSXML ActiveX */ + for (var i=0;i < JSONRpcClient.msxmlNames.length; i++) { + try { + JSONRpcClient.httpObjectName = JSONRpcClient.msxmlNames[i]; + return new ActiveXObject(JSONRpcClient.msxmlNames[i]); + } catch (e) {} + } + + /* None found */ + JSONRpcClient.httpObjectName = null; + throw new JSONRpcClient.Exception(0, "Can't create XMLHttpRequest object"); +}; + diff --git a/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/Echo.java b/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/Echo.java new file mode 100644 index 0000000000..d34784905d --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/Echo.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.binding.jsonrpc; + +/** + * Interface of our sample JSONRPC service. + * + * @version $Rev: 537616 $ $Date: 2007-05-13 09:34:45 -0800 (Sun, 13 May 2007) $ + */ +public interface Echo { + + String echo(String msg); +} diff --git a/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/EchoComponentImpl.java b/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/EchoComponentImpl.java new file mode 100644 index 0000000000..748768419d --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/EchoComponentImpl.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.binding.jsonrpc; + + + +/** + * A simple client component that uses a reference with an JSONRPC binding. + * + * @version $Rev: 537616 $ $Date: 2007-05-13 09:34:45 -0800 (Sun, 13 May 2007) $ + */ +public class EchoComponentImpl implements Echo { + + public String echo(String msg) { + System.out.println("Echo: "+ msg); + return "echo: " + msg; + } +} diff --git a/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java b/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.java new file mode 100644 index 0000000000..f7ed9d1d27 --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/test/java/org/apache/tuscany/sca/binding/jsonrpc/JSONRPCServiceTestCase.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.binding.jsonrpc; + +import java.io.ByteArrayInputStream; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.json.JSONObject; + +import com.meterware.httpunit.PostMethodWebRequest; +import com.meterware.httpunit.WebConversation; +import com.meterware.httpunit.WebRequest; +import com.meterware.httpunit.WebResponse; + +/** + * @version $Rev: 616286 $ $Date: 2008-01-29 04:38:29 -0800 (Tue, 29 Jan 2008) $ + */ +public class JSONRPCServiceTestCase extends TestCase { + + private static final String SERVICE_PATH = "/EchoService"; + + private static final String SERVICE_URL = "http://localhost:8085/SCADomain" + SERVICE_PATH; + + private SCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = SCADomain.newInstance("JSONRPCBinding.composite"); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + + public void testJSONRPCBinding() throws Exception { + JSONObject jsonRequest = new JSONObject("{ \"method\": \"echo\", \"params\": [\"Hello JSON-RPC\"], \"id\": 1}"); + + WebConversation wc = new WebConversation(); + WebRequest request = new PostMethodWebRequest( SERVICE_URL, new ByteArrayInputStream(jsonRequest.toString().getBytes("UTF-8")),"application/json"); + WebResponse response = wc.getResource(request); + + assertEquals(200, response.getResponseCode()); + JSONObject jsonResp = new JSONObject(response.getText()); + assertEquals("echo: Hello JSON-RPC", jsonResp.getString("result")); + } + + +} diff --git a/branches/sca-android/binding-jsonrpc/src/test/resources/JSONRPCBinding.composite b/branches/sca-android/binding-jsonrpc/src/test/resources/JSONRPCBinding.composite new file mode 100644 index 0000000000..491b42c69c --- /dev/null +++ b/branches/sca-android/binding-jsonrpc/src/test/resources/JSONRPCBinding.composite @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/.classpath b/branches/sca-android/calculator-android/.classpath new file mode 100644 index 0000000000..6f78dd6f3c --- /dev/null +++ b/branches/sca-android/calculator-android/.classpath @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/.project b/branches/sca-android/calculator-android/.project new file mode 100644 index 0000000000..e77a01d623 --- /dev/null +++ b/branches/sca-android/calculator-android/.project @@ -0,0 +1,33 @@ + + + calculator-android + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/branches/sca-android/calculator-android/AndroidManifest.xml b/branches/sca-android/calculator-android/AndroidManifest.xml new file mode 100644 index 0000000000..8f419508ce --- /dev/null +++ b/branches/sca-android/calculator-android/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/drawable/icon.png b/branches/sca-android/calculator-android/res/drawable/icon.png new file mode 100644 index 0000000000..64e3601c23 Binary files /dev/null and b/branches/sca-android/calculator-android/res/drawable/icon.png differ diff --git a/branches/sca-android/calculator-android/res/layout/main.xml b/branches/sca-android/calculator-android/res/layout/main.xml new file mode 100644 index 0000000000..469c950462 --- /dev/null +++ b/branches/sca-android/calculator-android/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + diff --git a/branches/sca-android/calculator-android/res/raw/calculator_composite b/branches/sca-android/calculator-android/res/raw/calculator_composite new file mode 100644 index 0000000000..90872041b0 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/calculator_composite @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca.xsd b/branches/sca-android/calculator-android/res/raw/sca.xsd new file mode 100644 index 0000000000..e108342693 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca.xsd @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_all.xsd b/branches/sca-android/calculator-android/res/raw/sca_all.xsd new file mode 100644 index 0000000000..6e3b848a53 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_all.xsd @@ -0,0 +1,32 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_binding_ejb.xsd b/branches/sca-android/calculator-android/res/raw/sca_binding_ejb.xsd new file mode 100644 index 0000000000..0e7e40432c --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_binding_ejb.xsd @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca_binding_jms.xsd b/branches/sca-android/calculator-android/res/raw/sca_binding_jms.xsd new file mode 100644 index 0000000000..868a9d64e0 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_binding_jms.xsd @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca_binding_sca.xsd b/branches/sca-android/calculator-android/res/raw/sca_binding_sca.xsd new file mode 100644 index 0000000000..8005cda8a6 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_binding_sca.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_binding_webservice.xsd b/branches/sca-android/calculator-android/res/raw/sca_binding_webservice.xsd new file mode 100644 index 0000000000..92446c0338 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_binding_webservice.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca_core.xsd b/branches/sca-android/calculator-android/res/raw/sca_core.xsd new file mode 100644 index 0000000000..20e0a6901c --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_core.xsd @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_definitions.xsd b/branches/sca-android/calculator-android/res/raw/sca_definitions.xsd new file mode 100644 index 0000000000..4676d34eeb --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_definitions.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_implementation_bpel.xsd b/branches/sca-android/calculator-android/res/raw/sca_implementation_bpel.xsd new file mode 100644 index 0000000000..80141a57af --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_implementation_bpel.xsd @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_implementation_composite_xsd b/branches/sca-android/calculator-android/res/raw/sca_implementation_composite_xsd new file mode 100644 index 0000000000..2486653235 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_implementation_composite_xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca_implementation_cpp.xsd b/branches/sca-android/calculator-android/res/raw/sca_implementation_cpp.xsd new file mode 100644 index 0000000000..1d157d9504 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_implementation_cpp.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca_implementation_ejb.xsd b/branches/sca-android/calculator-android/res/raw/sca_implementation_ejb.xsd new file mode 100644 index 0000000000..850b854fd5 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_implementation_ejb.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_implementation_java.xsd b/branches/sca-android/calculator-android/res/raw/sca_implementation_java.xsd new file mode 100644 index 0000000000..792ad407b3 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_implementation_java.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_implementation_spring.xsd b/branches/sca-android/calculator-android/res/raw/sca_implementation_spring.xsd new file mode 100644 index 0000000000..a9ef307bed --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_implementation_spring.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_interface_cpp.xsd b/branches/sca-android/calculator-android/res/raw/sca_interface_cpp.xsd new file mode 100644 index 0000000000..9cae7e3685 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_interface_cpp.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/sca_interface_java.xsd b/branches/sca-android/calculator-android/res/raw/sca_interface_java.xsd new file mode 100644 index 0000000000..3f9eb25440 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_interface_java.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_interface_wsdl.xsd b/branches/sca-android/calculator-android/res/raw/sca_interface_wsdl.xsd new file mode 100644 index 0000000000..c161d98f88 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_interface_wsdl.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/sca_policy.xsd b/branches/sca-android/calculator-android/res/raw/sca_policy.xsd new file mode 100644 index 0000000000..1ae1c9dfdc --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/sca_policy.xsd @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca.xsd new file mode 100644 index 0000000000..33b7c5099b --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca.xsd @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + __> + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_atom.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_atom.xsd new file mode 100644 index 0000000000..1423a7ee87 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_atom.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_dwr.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_dwr.xsd new file mode 100644 index 0000000000..98b17bbb8b --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_dwr.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_http.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_http.xsd new file mode 100644 index 0000000000..4d709353d0 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_http.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_jsonrpc.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_jsonrpc.xsd new file mode 100644 index 0000000000..e03d6feb02 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_jsonrpc.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_notification.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_notification.xsd new file mode 100644 index 0000000000..d1b23e8826 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_notification.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rmi.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rmi.xsd new file mode 100644 index 0000000000..7815e390e4 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rmi.xsd @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rss.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rss.xsd new file mode 100644 index 0000000000..8fd10cc781 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_binding_rss.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_node.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_node.xsd new file mode 100644 index 0000000000..1943c98d70 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_node.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_notification.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_notification.xsd new file mode 100644 index 0000000000..1c4c6d7aeb --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_notification.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_osgi.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_osgi.xsd new file mode 100644 index 0000000000..9fedc2bb84 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_osgi.xsd @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_resource.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_resource.xsd new file mode 100644 index 0000000000..e37b2c47ee --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_resource.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_script.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_script.xsd new file mode 100644 index 0000000000..a13643d148 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_script.xsd @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_widget.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_widget.xsd new file mode 100644 index 0000000000..1afb30c106 --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_widget.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_xquery.xsd b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_xquery.xsd new file mode 100644 index 0000000000..875f0da1dc --- /dev/null +++ b/branches/sca-android/calculator-android/res/raw/tuscany_sca_implementation_xquery.xsd @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/calculator-android/res/values/strings.xml b/branches/sca-android/calculator-android/res/values/strings.xml new file mode 100644 index 0000000000..91b584c887 --- /dev/null +++ b/branches/sca-android/calculator-android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Calculator + diff --git a/branches/sca-android/calculator-android/src/calculator/AddService.java b/branches/sca-android/calculator-android/src/calculator/AddService.java new file mode 100644 index 0000000000..188451ebac --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/AddService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +/** + * The Add service interface + */ +public interface AddService { + + double add(double n1, double n2); + +} diff --git a/branches/sca-android/calculator-android/src/calculator/AddServiceImpl.java b/branches/sca-android/calculator-android/src/calculator/AddServiceImpl.java new file mode 100644 index 0000000000..7ca8fb04b5 --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/AddServiceImpl.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 calculator; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * An implementation of the Add service + */ +public class AddServiceImpl implements AddService { + + public double add(double n1, double n2) { + Logger logger = Logger.getLogger("calculator"); + logger.log(Level.FINEST, "Adding " + n1 + " and " + n2); + return n1 + n2; + } + +} diff --git a/branches/sca-android/calculator-android/src/calculator/CalculatorService.java b/branches/sca-android/calculator-android/src/calculator/CalculatorService.java new file mode 100644 index 0000000000..031fa8b912 --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/CalculatorService.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 calculator; + + +/** + * The Calculator service interface. + */ +public interface CalculatorService { + + double add(double n1, double n2); + + double subtract(double n1, double n2); + + double multiply(double n1, double n2); + + double divide(double n1, double n2); + +} diff --git a/branches/sca-android/calculator-android/src/calculator/CalculatorServiceImpl.java b/branches/sca-android/calculator-android/src/calculator/CalculatorServiceImpl.java new file mode 100644 index 0000000000..3d861f2018 --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/CalculatorServiceImpl.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 calculator; + +import org.osoa.sca.annotations.Reference; + + +/** + * An implementation of the Calculator service. + */ +public class CalculatorServiceImpl implements CalculatorService { + + private AddService addService; + private SubtractService subtractService; + private MultiplyService multiplyService; + private DivideService divideService; + + @Reference + public void setAddService(AddService addService) { + this.addService = addService; + } + + @Reference + public void setSubtractService(SubtractService subtractService) { + this.subtractService = subtractService; + } + + @Reference + public void setDivideService(DivideService divideService) { + this.divideService = divideService; + } + + @Reference + public void setMultiplyService(MultiplyService multiplyService) { + this.multiplyService = multiplyService; + } + + public double add(double n1, double n2) { + return addService.add(n1, n2); + } + + public double subtract(double n1, double n2) { + return subtractService.subtract(n1, n2); + } + + public double multiply(double n1, double n2) { + return multiplyService.multiply(n1, n2); + } + + public double divide(double n1, double n2) { + return divideService.divide(n1, n2); + } + +} diff --git a/branches/sca-android/calculator-android/src/calculator/DivideService.java b/branches/sca-android/calculator-android/src/calculator/DivideService.java new file mode 100644 index 0000000000..30d248208b --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/DivideService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +/** + * The divide service interface + */ +public interface DivideService { + + double divide(double n1, double n2); + +} diff --git a/branches/sca-android/calculator-android/src/calculator/DivideServiceImpl.java b/branches/sca-android/calculator-android/src/calculator/DivideServiceImpl.java new file mode 100644 index 0000000000..1323edf55a --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/DivideServiceImpl.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 calculator; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * An implementation of the Divide service. + */ +public class DivideServiceImpl implements DivideService { + + public double divide(double n1, double n2) { + Logger logger = Logger.getLogger("calculator"); + logger.log(Level.FINEST, "Dividing " + n1 + " with " + n2); + return n1 / n2; + } + +} diff --git a/branches/sca-android/calculator-android/src/calculator/MultiplyService.java b/branches/sca-android/calculator-android/src/calculator/MultiplyService.java new file mode 100644 index 0000000000..5290605938 --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/MultiplyService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +/** + * The interface for the multiply service + */ +public interface MultiplyService { + + double multiply(double n1, double n2); + +} diff --git a/branches/sca-android/calculator-android/src/calculator/MultiplyServiceImpl.java b/branches/sca-android/calculator-android/src/calculator/MultiplyServiceImpl.java new file mode 100644 index 0000000000..91b803bc9e --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/MultiplyServiceImpl.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 calculator; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * An implementation of the Multiply service. + */ +public class MultiplyServiceImpl implements MultiplyService { + + public double multiply(double n1, double n2) { + Logger logger = Logger.getLogger("calculator"); + logger.log(Level.FINEST, "Multiplying " + n1 + " with " + n2); + return n1 * n2; + } + +} diff --git a/branches/sca-android/calculator-android/src/calculator/SubtractService.java b/branches/sca-android/calculator-android/src/calculator/SubtractService.java new file mode 100644 index 0000000000..bf0d1882b6 --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/SubtractService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +/** + * The interface for the multiply service + */ +public interface SubtractService { + + double subtract(double n1, double n2); + +} diff --git a/branches/sca-android/calculator-android/src/calculator/SubtractServiceImpl.java b/branches/sca-android/calculator-android/src/calculator/SubtractServiceImpl.java new file mode 100644 index 0000000000..58cc4a3547 --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/SubtractServiceImpl.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 calculator; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * An implementation of the subtract service. + */ +public class SubtractServiceImpl implements SubtractService { + + public double subtract(double n1, double n2) { + Logger logger = Logger.getLogger("calculator"); + logger.log(Level.FINEST, "Subtracting " + n1 + " from " + n2); + return n1 - n2; + } + +} diff --git a/branches/sca-android/calculator-android/src/calculator/android/CalculatorClient.java b/branches/sca-android/calculator-android/src/calculator/android/CalculatorClient.java new file mode 100644 index 0000000000..7d6a6613ed --- /dev/null +++ b/branches/sca-android/calculator-android/src/calculator/android/CalculatorClient.java @@ -0,0 +1,36 @@ +package calculator.android; + +import org.apache.tuscany.sca.host.embedded.SCADomain; + +import calculator.CalculatorService; +import android.app.Activity; +import android.os.Bundle; +import android.widget.TextView; + +public class CalculatorClient extends Activity { + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + StringBuffer sb = new StringBuffer(); + + SCADomain scaDomain = SCADomain.newInstance(this, "dex://calculator.android/raw/calculator.composite"); + + CalculatorService calculatorService = + scaDomain.getService(CalculatorService.class, "CalculatorServiceComponent"); + + // Calculate + sb.append("3 + 2=" + calculatorService.add(3, 2)); + sb.append("3 - 2=" + calculatorService.subtract(3, 2)); + sb.append("3 * 2=" + calculatorService.multiply(3, 2)); + sb.append("3 / 2=" + calculatorService.divide(3, 2)); + + scaDomain.close(); + + TextView tv = new TextView(this); + tv.setText(sb.toString()); + setContentView(tv); + + } +} \ No newline at end of file diff --git a/branches/sca-android/contribution-impl/.classpath b/branches/sca-android/contribution-impl/.classpath new file mode 100644 index 0000000000..55f73705a4 --- /dev/null +++ b/branches/sca-android/contribution-impl/.classpath @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/contribution-impl/.project b/branches/sca-android/contribution-impl/.project new file mode 100644 index 0000000000..3960f1489e --- /dev/null +++ b/branches/sca-android/contribution-impl/.project @@ -0,0 +1,26 @@ + + tuscany-contribution-impl + Parent POM defining settings that can be used across Tuscany + + tuscany-contribution + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-contribution-java + tuscany-core-spi + tuscany-sca-api + tuscany-contribution-namespace + tuscany-contribution-resource + tuscany-contribution-xml + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/contribution-impl/DISCLAIMER b/branches/sca-android/contribution-impl/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/contribution-impl/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/contribution-impl/LICENSE b/branches/sca-android/contribution-impl/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/contribution-impl/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/branches/sca-android/contribution-impl/NOTICE b/branches/sca-android/contribution-impl/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/contribution-impl/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/contribution-impl/pom.xml b/branches/sca-android/contribution-impl/pom.xml new file mode 100644 index 0000000000..1f8855dca9 --- /dev/null +++ b/branches/sca-android/contribution-impl/pom.xml @@ -0,0 +1,69 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-contribution-impl + Apache Tuscany SCA Contribution Model Implementation + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-namespace + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-resource + 2.0-incubating-SNAPSHOT + + + + org.codehaus.woodstox + wstx-asl + 3.2.1 + runtime + + + diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/DexContributionProcessor.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/DexContributionProcessor.java new file mode 100644 index 0000000000..83c209180d --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/DexContributionProcessor.java @@ -0,0 +1,124 @@ +package org.apache.tuscany.sca.contribution.processor.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.android.DexResource; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.service.ContributionException; + +public class DexContributionProcessor implements PackageProcessor { + + public URL getArtifactURL(URL packageSourceURL, URI artifact) + throws MalformedURLException { + return new URL(artifact.toString()); + } + + public List getArtifacts(URL packageSourceURL, InputStream inputStream) + throws ContributionException, IOException { + + ArrayList uris = new ArrayList(); + DexResource res = new DexResource(packageSourceURL); + + URI[] contentFiles = res.getContentFiles(); + + for (URI uri : contentFiles) { + String fileName = DexResource.getFile(uri.getPath()); + URL url = uri.toURL(); + + if (fileName != null) { + + if (fileName.endsWith("_composite")) { + + url.openConnection(); + try { + XMLStreamReader r = XMLInputFactory.newInstance() + .createXMLStreamReader(url.openStream()); + + while (r.hasNext()) { + + if (r.isStartElement()) { + QName name = r.getName(); + + if ("implementation.java".equals(name + .getLocalPart())) { + int attributeCount = r.getAttributeCount(); + + for (int i = 0; i < attributeCount; i++) { + + if (r.getAttributeLocalName(i).equals( + "class")) { + StringBuffer sb = new StringBuffer( + "dex://"); + sb.append( + r.getAttributeValue(i) + .replace('.', '/')) + .append(".class"); + + try { + uris + .add(new URI(sb + .toString())); + } catch (URISyntaxException e) { + } + + break; + + } + + } + + } + + } + + r.next(); + + } + + } catch (XMLStreamException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (FactoryConfigurationError e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + StringBuffer sb = new StringBuffer("dex://"); + sb.append(url.getHost()).append(url.getPath()); + sb.delete(sb.length() - 10, sb.length()).append( + ".composite"); + + try { + uris.add(new URI(sb.toString())); + } catch (URISyntaxException e) { + continue; + } + + } + + } + + } + + return uris; + + } + + public String getPackageType() { + return "application/x-dex"; + } + +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/FolderContributionProcessor.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/FolderContributionProcessor.java new file mode 100644 index 0000000000..6793855efc --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/FolderContributionProcessor.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.contribution.processor.impl; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.contribution.PackageType; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.service.ContributionException; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; + +/** + * Folder contribution package processor. + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +public class FolderContributionProcessor implements PackageProcessor { + + public FolderContributionProcessor() { + } + + public String getPackageType() { + return PackageType.FOLDER; + } + + /** + * Recursively traverse a root directory + * + * @param fileList + * @param file + * @param root + * @throws IOException + */ + private static void traverse(List fileList, final File file, final File root) throws IOException { + // Allow privileged access to test file. Requires FilePermissions in security policy file. + Boolean isFile = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return file.isFile(); + } + }); + if (isFile) { + fileList.add(AccessController.doPrivileged(new PrivilegedAction() { + public URI run() { + return root.toURI().relativize(file.toURI()); + } + })); + } else { + // Allow privileged access to test file. Requires FilePermissions in security policy + // file. + Boolean isDirectory = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return file.isDirectory(); + } + }); + if (isDirectory) { + String uri = AccessController.doPrivileged(new PrivilegedAction() { + public URI run() { + return root.toURI().relativize(file.toURI()); + } + }).toString(); + + if (uri.endsWith("/")) { + uri = uri.substring(0, uri.length() - 1); + } + fileList.add(URI.create(uri)); + + // Allow privileged access to list files. Requires FilePermission in security + // policy. + File[] files = AccessController.doPrivileged(new PrivilegedAction() { + public File[] run() { + return file.listFiles(); + } + }); + for (File f : files) { + if (!f.getName().startsWith(".")) { + traverse(fileList, f, root); + } + } + } + } + } + + public URL getArtifactURL(URL sourceURL, URI artifact) throws MalformedURLException { + return new URL(sourceURL, artifact.toString()); + } + + public List getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, + IOException { + if (packageSourceURL == null) { + throw new IllegalArgumentException("Invalid null package source URL."); + } + + List artifacts = new ArrayList(); + + try { + // Assume the root is a jar file + final File rootFolder = new File(packageSourceURL.toURI()); + // Allow privileged access to test file. Requires FilePermissions in security policy + // file. + Boolean isDirectory = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return rootFolder.isDirectory(); + } + }); + if (isDirectory) { + // Allow privileged access to test file. Requires FilePermissions in security policy + // file. + Boolean folderExists = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return rootFolder.exists(); + } + }); + if (!folderExists) { + throw new ContributionReadException(rootFolder.getAbsolutePath()); + } + + // Security consideration. This method gathers URIs of enclosed + // artifacts. The URIs are protected by the policy when a user + // yries to open those URLs. + traverse(artifacts, rootFolder, rootFolder); + } + + } catch (URISyntaxException e) { + throw new ContributionReadException(packageSourceURL.toExternalForm(), e); + } + + return artifacts; + } +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/JarContributionProcessor.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/JarContributionProcessor.java new file mode 100644 index 0000000000..785f31c72a --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/JarContributionProcessor.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.processor.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +import org.apache.tuscany.sca.contribution.PackageType; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.service.ContributionException; + +/** + * Jar Contribution package processor. + * + * @version $Rev: 616194 $ $Date: 2008-01-28 23:49:21 -0800 (Mon, 28 Jan 2008) $ + */ +public class JarContributionProcessor implements PackageProcessor { + + public JarContributionProcessor() { + } + + public String getPackageType() { + return PackageType.JAR; + } + + public URL getArtifactURL(URL sourceURL, URI artifact) throws MalformedURLException { + if (sourceURL.toString().startsWith("jar:")) { + return new URL(sourceURL, artifact.toString()); + } else { + return new URL("jar:" + sourceURL.toExternalForm() + "!/" + artifact); + } + } + + public List getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, + IOException { + if (packageSourceURL == null) { + throw new IllegalArgumentException("Invalid null package source URL."); + } + + if (inputStream == null) { + throw new IllegalArgumentException("Invalid null source inputstream."); + } + + // Assume the root is a jar file + JarInputStream jar = new JarInputStream(inputStream); + try { + Set names = new HashSet(); + while (true) { + JarEntry entry = jar.getNextJarEntry(); + if (entry == null) { + // EOF + break; + } + + // FIXME: Maybe we should externalize the filter as a property + String name = entry.getName(); + if (!name.startsWith(".")) { + + // Trim trailing / + if (name.endsWith("/")) { + name = name.substring(0, name.length() - 1); + } + + // Add the entry name + if (!names.contains(name)) { + names.add(name); + + // Add parent folder names to the list too + for (;;) { + int s = name.lastIndexOf('/'); + if (s == -1) { + name = ""; + } else { + name = name.substring(0, s); + } + if (!names.contains(name)) { + names.add(name); + } else { + break; + } + } + } + } + } + + // Return list of URIs + List artifacts = new ArrayList(); + for (String name: names) { + artifacts.add(URI.create(name)); + } + return artifacts; + + } finally { + jar.close(); + } + } +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java new file mode 100644 index 0000000000..3425864c62 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java @@ -0,0 +1,333 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.service.impl; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionRepository; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.contribution.service.util.IOHelper; + +/** + * The default implementation of ContributionRepository + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +public class ContributionRepositoryImpl implements ContributionRepository { + private static final String NS = "http://tuscany.apache.org/xmlns/1.0-SNAPSHOT"; + private static final String DOMAIN_INDEX_FILENAME = "sca-domain.xml"; + private final File rootFile; + private Map contributionLocations = new HashMap(); + + private Map contributionMap = new HashMap(); + private List contributions = new ArrayList(); + + private URI domain; + private XMLInputFactory factory; + + /** + * Constructor with repository root + * + * @param repository + * @param factory + */ + public ContributionRepositoryImpl(final String repository, XMLInputFactory factory) throws IOException { + String root = repository; + if (repository == null) { + root = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + // Default to /.tuscany/domains/local/ + String userHome = System.getProperty("user.home"); + String slash = File.separator; + return userHome + slash + ".tuscany" + slash + "domains" + slash + "local" + slash; + } + }); + } + + // Allow privileged access to File. Requires FilePermission in security policy file. + final String finalRoot = root; + this.rootFile = AccessController.doPrivileged(new PrivilegedAction() { + public File run() { + return new File(finalRoot); + } + }); + + // Allow privileged access to File. Requires FilePermission in security policy file. + this.domain = AccessController.doPrivileged(new PrivilegedAction() { + public URI run() { + return rootFile.toURI(); + } + }); + + // Allow privileged access to mkdir. Requires FilePermission in security policy file. + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws IOException { + FileHelper.forceMkdir(rootFile); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw (IOException)e.getException(); + } + + // Allow privileged access to test file. Requires FilePermissions in security policy file. + Boolean notDirectory = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return (!rootFile.exists() || !rootFile.isDirectory() || !rootFile.canRead()); + } + }); + if (notDirectory) { + throw new IOException("The root is not a directory: " + repository); + } + this.factory = factory; + } + + public URI getDomain() { + return domain; + } + + /** + * Resolve contribution location in the repository -> root repository / + * contribution file -> contribution group id / artifact id / version + * + * @param contribution + * @return + */ + private File mapToFile(URL sourceURL) { + String fileName = FileHelper.toFile(sourceURL).getName(); + return new File(rootFile, "contributions" + File.separator + fileName); + } + + /** + * Write a specific source InputStream to a file on disk + * + * @param source contents of the file to be written to disk + * @param target file to be written + * @throws IOException + */ + public static void copy(InputStream source, File target) throws IOException { + BufferedOutputStream out = null; + BufferedInputStream in = null; + + try { + out = new BufferedOutputStream(new FileOutputStream(target)); + in = new BufferedInputStream(source); + IOHelper.copy(in, out); + } finally { + IOHelper.closeQuietly(out); + IOHelper.closeQuietly(in); + } + } + + public URL store(String contribution, URL sourceURL, InputStream contributionStream) throws IOException { + // where the file should be stored in the repository + File location = mapToFile(sourceURL); + FileHelper.forceMkdir(location.getParentFile()); + + copy(contributionStream, location); + + // add contribution to repositoryContent + URL contributionURL = location.toURL(); + URI relative = rootFile.toURI().relativize(location.toURI()); + contributionLocations.put(contribution, relative.toString()); + saveMap(); + + return contributionURL; + } + + public URL store(String contribution, URL sourceURL) throws IOException { + // where the file should be stored in the repository + File location = mapToFile(sourceURL); + File source = FileHelper.toFile(sourceURL); + if (source == null || source.isFile()) { + URLConnection connection = sourceURL.openConnection(); + connection.setUseCaches(false); + InputStream is = connection.getInputStream(); + try { + return store(contribution, sourceURL, is); + } finally { + IOHelper.closeQuietly(is); + } + } + + FileHelper.forceMkdir(location); + FileHelper.copyDirectory(source, location); + + // add contribution to repositoryContent + URI relative = rootFile.toURI().relativize(location.toURI()); + contributionLocations.put(contribution, relative.toString()); + saveMap(); + + return location.toURL(); + } + + public URL find(String contribution) { + if (contribution == null) { + return null; + } + String location = contributionLocations.get(contribution); + if (location == null) { + return null; + } + try { + return new File(rootFile, location).toURL(); + } catch (MalformedURLException e) { + // Should not happen + throw new AssertionError(e); + } + } + + public void remove(String contribution) { + URL contributionURL = this.find(contribution); + if (contributionURL != null) { + // remove + try { + FileHelper.forceDelete(FileHelper.toFile(contributionURL)); + this.contributionLocations.remove(contribution); + saveMap(); + } catch (IOException ioe) { + // handle file could not be removed + } + } + } + + public List list() { + return new ArrayList(contributionLocations.keySet()); + } + + public void init() { + File domainFile = new File(rootFile, "sca-domain.xml"); + if (!domainFile.isFile()) { + return; + } + FileInputStream is; + try { + is = new FileInputStream(domainFile); + } catch (FileNotFoundException e) { + return; + } + try { + XMLStreamReader reader = factory.createXMLStreamReader(new InputStreamReader(is, "UTF-8")); + while (reader.hasNext()) { + switch (reader.getEventType()) { + case XMLStreamConstants.START_ELEMENT: + String name = reader.getName().getLocalPart(); + if ("domain".equals(name)) { + String uri = reader.getAttributeValue(null, "uri"); + if (uri != null) { + domain = URI.create(uri); + } + } + if ("contribution".equals(name)) { + String uri = reader.getAttributeValue(null, "uri"); + String location = reader.getAttributeValue(null, "location"); + contributionLocations.put(uri, location); + } + break; + default: + break; + } + reader.next(); + } + } catch (Exception e) { + // Ignore + } finally { + IOHelper.closeQuietly(is); + } + } + + private void saveMap() { + File domainFile = new File(rootFile, DOMAIN_INDEX_FILENAME); + FileOutputStream os = null; + try { + os = new FileOutputStream(domainFile); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, "UTF-8")); + writer.println(""); + writer.println(""); + for (Map.Entry e : contributionLocations.entrySet()) { + writer.println(" "); + } + writer.println(""); + writer.flush(); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } finally { + IOHelper.closeQuietly(os); + } + } + + public void destroy() { + } + + public void addContribution(Contribution contribution) { + contributionMap.put(contribution.getURI(), contribution); + contributions.add(contribution); + } + + public void removeContribution(Contribution contribution) { + contributionMap.remove(contribution.getURI()); + contributions.remove(contribution); + } + + public void updateContribution(Contribution contribution) { + Contribution oldContribution = contributionMap.remove(contribution.getURI()); + contributions.remove(oldContribution); + contributionMap.put(contribution.getURI(), contribution); + contributions.add(contribution); + } + + public Contribution getContribution(String uri) { + return contributionMap.get(uri); + } + + public List getContributions() { + return Collections.unmodifiableList(contributions); + } + +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java new file mode 100644 index 0000000000..ed3022bb3b --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java @@ -0,0 +1,520 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.service.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; + +import org.apache.tuscany.sca.android.ContextRegistry; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionException; +import org.apache.tuscany.sca.contribution.service.ContributionRepository; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.ExtensibleContributionListener; +import org.apache.tuscany.sca.contribution.service.util.IOHelper; +import org.apache.tuscany.sca.contribution.xml.ContributionMetadataDocumentProcessor; +import org.apache.tuscany.sca.definitions.SCADefinitions; + +import android.content.Context; + +/** + * Service interface that manages artifacts contributed to a Tuscany runtime. + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +/** + * + */ +public class ContributionServiceImpl implements ContributionService { + + /** + * Repository where contributions are stored. Usually set by injection. + */ + private ContributionRepository contributionRepository; + + /** + * Registry of available package processors. + */ + private PackageProcessor packageProcessor; + + /** + * Registry of available artifact processors + */ + + private URLArtifactProcessor artifactProcessor; + + /** + * Registry of available StAX processors, + * used for loading contribution metadata in a extensible way + */ + private StAXArtifactProcessor staxProcessor; + + /** + * Event listener for contribution operations + */ + private ExtensibleContributionListener contributionListener; + + /** + * Registry of available model resolvers + */ + + private ModelResolverExtensionPoint modelResolvers; + + /** + * Model factory extension point + */ + + private ModelFactoryExtensionPoint modelFactories; + + /** + * XML factory used to create reader instance to load contribution metadata + */ + private XMLInputFactory xmlFactory; + + /** + * Assembly factory + */ + private AssemblyFactory assemblyFactory; + + /** + * Contribution model factory + */ + private ContributionFactory contributionFactory; + + + private ModelResolver domainResolver; + + + private List scaDefinitionsSink = null; + + private String COMPOSITE_FILE_EXTN = ".composite"; + + public ContributionServiceImpl(ContributionRepository repository, + PackageProcessor packageProcessor, + URLArtifactProcessor documentProcessor, + StAXArtifactProcessor staxProcessor, + ExtensibleContributionListener contributionListener, + ModelResolver domainResolver, + ModelResolverExtensionPoint modelResolvers, + ModelFactoryExtensionPoint modelFactories, + AssemblyFactory assemblyFactory, + ContributionFactory contributionFactory, + XMLInputFactory xmlFactory, + List scaDefnSink) { + super(); + this.contributionRepository = repository; + this.packageProcessor = packageProcessor; + this.artifactProcessor = documentProcessor; + this.staxProcessor = staxProcessor; + this.contributionListener = contributionListener; + this.modelResolvers = modelResolvers; + this.modelFactories = modelFactories; + this.xmlFactory = xmlFactory; + this.assemblyFactory = assemblyFactory; + this.contributionFactory = contributionFactory; + this.domainResolver = domainResolver; + this.scaDefinitionsSink = scaDefnSink; + } + + public Contribution contribute(String contributionURI, URL sourceURL, boolean storeInRepository) + throws ContributionException, IOException { + if (contributionURI == null) { + throw new IllegalArgumentException("URI for the contribution is null"); + } + if (sourceURL == null) { + throw new IllegalArgumentException("Source URL for the contribution is null"); + } + + return addContribution(contributionURI, sourceURL, null, null, storeInRepository); + } + + public Contribution contribute(String contributionURI, + URL sourceURL, + ModelResolver modelResolver, + boolean storeInRepository) throws ContributionException, IOException { + if (contributionURI == null) { + throw new IllegalArgumentException("URI for the contribution is null"); + } + if (sourceURL == null) { + throw new IllegalArgumentException("Source URL for the contribution is null"); + } + + return addContribution(contributionURI, sourceURL, null, modelResolver, storeInRepository); + } + + public Contribution contribute(String contributionURI, URL sourceURL, InputStream input) + throws ContributionException, IOException { + + return addContribution(contributionURI, sourceURL, input, null, true); + } + + public Contribution contribute(String contributionURI, URL sourceURL, InputStream input, ModelResolver modelResolver) + throws ContributionException, IOException { + + return addContribution(contributionURI, sourceURL, input, modelResolver, true); + } + + public Contribution getContribution(String uri) { + return this.contributionRepository.getContribution(uri); + } + + /** + * Remove a contribution and notify listener that contribution was removed + */ + public void remove(String uri) throws ContributionException { + Contribution contribution = contributionRepository.getContribution(uri); + this.contributionRepository.removeContribution(contribution); + this.contributionListener.contributionRemoved(this.contributionRepository, contribution); + } + + /** + * Add a composite model to the contribution + */ + public void addDeploymentComposite(Contribution contribution, Composite composite) throws ContributionException { + Artifact artifact = this.contributionFactory.createArtifact(); + artifact.setURI(composite.getURI()); + artifact.setModel(composite); + + contribution.getArtifacts().add(artifact); + + contribution.getDeployables().add(composite); + } + + /** + * Utility/Helper methods for contribution service + */ + + /** + * Perform read of the contribution metadata loader (sca-contribution.xml and sca-contribution-generated.xml) + * When the two metadata files are available, the information provided are merged, and the sca-contribution has priorities + * + * @param sourceURL + * @return Contribution + * @throws ContributionException + */ + private Contribution readContributionMetadata(URL sourceURL) throws ContributionException { + Contribution contributionMetadata = contributionFactory.createContribution(); + + ContributionMetadataDocumentProcessor metadataDocumentProcessor = + new ContributionMetadataDocumentProcessor(staxProcessor, xmlFactory); + + /* final URL[] urls = {sourceURL}; + // Allow access to create classloader. Requires RuntimePermission in security policy. + URLClassLoader cl = AccessController.doPrivileged(new PrivilegedAction() { + public URLClassLoader run() { + return new URLClassLoader(urls, null); + } + }); + for (String path: new String[]{ + Contribution.SCA_CONTRIBUTION_GENERATED_META, + Contribution.SCA_CONTRIBUTION_META}) { + URL url = cl.getResource(path); + if (url != null) { + Contribution contribution = metadataDocumentProcessor.read(sourceURL, URI.create(path), url); + contributionMetadata.getImports().addAll(contribution.getImports()); + contributionMetadata.getExports().addAll(contribution.getExports()); + contributionMetadata.getDeployables().addAll(contribution.getDeployables()); + } + }*/ + + // For debugging purposes, write it back to XML + // if (contributionMetadata != null) { + // try { + // ByteArrayOutputStream bos = new ByteArrayOutputStream(); + // XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + // outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); + // staxProcessor.write(contributionMetadata, outputFactory.createXMLStreamWriter(bos)); + // Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(bos.toByteArray())); + // OutputFormat format = new OutputFormat(); + // format.setIndenting(true); + // format.setIndent(2); + // XMLSerializer serializer = new XMLSerializer(System.out, format); + // serializer.serialize(document); + // } catch (Exception e) { + // e.printStackTrace(); + // } + // } + + return contributionMetadata; + } + + /** + * Note: + * + * @param contributionURI ContributionID + * @param sourceURL contribution location + * @param contributionStream contribution content + * @param storeInRepository flag if we store the contribution into the + * repository or not + * @return the contribution model representing the contribution + * @throws IOException + * @throws DeploymentException + */ + private Contribution addContribution(String contributionURI, + URL sourceURL, + InputStream contributionStream, + ModelResolver modelResolver, + boolean storeInRepository) throws IOException, ContributionException { + + if (contributionStream == null && sourceURL == null) { + throw new IllegalArgumentException("The content of the contribution is null."); + } + + // store the contribution in the contribution repository + URL locationURL = sourceURL; + if (contributionRepository != null && storeInRepository) { + if (contributionStream == null) { + locationURL = contributionRepository.store(contributionURI, sourceURL); + } else { + locationURL = contributionRepository.store(contributionURI, sourceURL, contributionStream); + } + } + + //initialize contribution based on it's metadata if available + Contribution contribution = readContributionMetadata(locationURL); + + // Create contribution model resolver + if (modelResolver == null) { + //FIXME Remove this domain resolver, visibility of policy declarations should be handled by + // the contribution import/export mechanism instead of this domainResolver hack. + modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, modelFactories, domainResolver); + } + + //set contribution initial information + contribution.setURI(contributionURI.toString()); + contribution.setLocation(locationURL.toString()); + contribution.setModelResolver(modelResolver); + + Context[] contexts = ContextRegistry.getContexts(new URL(contribution.getLocation()).getHost()); + + if (contexts.length > 0) { + contribution.setClassLoader(contexts[0].getClassLoader()); + } + + List contributionArtifacts = null; + + //NOTE: if a contribution is stored on the repository + //the stream would be consumed at this point + if (storeInRepository || contributionStream == null) { + URLConnection connection = sourceURL.openConnection(); + connection.setUseCaches(false); + // Allow access to open URL stream. Add FilePermission to added to security policy file. + final URLConnection finalConnection = connection; + try { + contributionStream = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public InputStream run() throws IOException { + return finalConnection.getInputStream(); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException)e.getException(); + } + + try { + // process the contribution + contributionArtifacts = this.packageProcessor.getArtifacts(locationURL, contributionStream); + } finally { + IOHelper.closeQuietly(contributionStream); + contributionStream = null; + } + } else { + // process the contribution + contributionArtifacts = this.packageProcessor.getArtifacts(locationURL, contributionStream); + } + + // Read all artifacts in the contribution + try { + // Allow access to read system properties. Requires PropertyPermission in security policy. + // Any security exceptions are caught and wrapped as ContributionException. + processReadPhase(contribution, contributionArtifacts); + } catch ( Exception e ) { + throw new ContributionException(e); + } + + // + this.contributionListener.contributionAdded(this.contributionRepository, contribution); + + // Resolve them + processResolvePhase(contribution); + + // Add all composites under META-INF/sca-deployables to the + // list of deployables + String prefix = Contribution.SCA_CONTRIBUTION_DEPLOYABLES; + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + if (artifact.getURI().startsWith(prefix)) { + Composite composite = (Composite)artifact.getModel(); + if (!contribution.getDeployables().contains(composite)) { + contribution.getDeployables().add(composite); + } + } + } + } + + // store the contribution on the registry + if (this.contributionRepository != null) { + this.contributionRepository.addContribution(contribution); + } + + return contribution; + } + + /** + * This utility method process each artifact and delegates to proper + * artifactProcessor to read the model and generate the in-memory representation + * + * @param contribution + * @param artifacts + * @throws ContributionException + * @throws MalformedURLException + */ + private void processReadPhase(Contribution contribution, List artifacts) throws ContributionException, + MalformedURLException, XMLStreamException { + + ModelResolver modelResolver = contribution.getModelResolver(); + URL contributionURL = new URL(contribution.getLocation()); + + List compositeUris = new ArrayList(); + + Object model = null; + for (URI anArtifactUri : artifacts) { + if ( anArtifactUri.toString().endsWith(COMPOSITE_FILE_EXTN)) { + compositeUris.add(anArtifactUri); + } else { + URL artifactURL = packageProcessor.getArtifactURL(new URL(contribution.getLocation()), anArtifactUri); + + // Add the deployed artifact model to the resolver + Artifact artifact = this.contributionFactory.createArtifact(); + artifact.setURI(anArtifactUri.toString()); + artifact.setLocation(artifactURL.toString()); + contribution.getArtifacts().add(artifact); + modelResolver.addModel(artifact); + + model = this.artifactProcessor.read(contributionURL, anArtifactUri, artifactURL); + + if (model != null) { + artifact.setModel(model); + + // Add the loaded model to the model resolver + modelResolver.addModel(model); + + if ( isSCADefnsFile(anArtifactUri) ) { + scaDefinitionsSink.add(model); + } + } + } + } + + for (URI anArtifactUri : compositeUris) { + URL artifactURL = packageProcessor.getArtifactURL(new URL(contribution.getLocation()), anArtifactUri); + + // Add the deployed artifact model to the resolver + Artifact artifact = this.contributionFactory.createArtifact(); + artifact.setURI(anArtifactUri.toString()); + artifact.setLocation(artifactURL.toString()); + contribution.getArtifacts().add(artifact); + modelResolver.addModel(artifact); + + model = this.artifactProcessor.read(contributionURL, anArtifactUri, artifactURL); + if (model != null) { + artifact.setModel(model); + // Add the loaded model to the model resolver + modelResolver.addModel(model); + } + } + } + + /** + * This utility method process each artifact and delegates to proper + * artifactProcessor to resolve the model references + * + * @param contribution + * @throws ContributionException + */ + @SuppressWarnings("unchecked") + private void processResolvePhase(Contribution contribution) throws ContributionException { + List composites = new ArrayList(); + + // for each artifact that was processed on the contribution + for (Artifact artifact : contribution.getArtifacts()) { + //leave the composites to be resolved at the end + if (artifact.getURI().endsWith(".composite")) { + composites.add(artifact); + } else { + // resolve the model object + if (artifact.getModel() != null) { + this.artifactProcessor.resolve(artifact.getModel(), contribution.getModelResolver()); + } + } + } + + //process each composite file + for (Artifact artifact : composites) { + // resolve the model object + if (artifact.getModel() != null) { + // System.out.println("Processing Resolve Phase : " + artifact.getURI()); + this.artifactProcessor.resolve(artifact.getModel(), contribution.getModelResolver()); + } + } + + //resolve deployables from contribution metadata + List resolvedDeployables = new ArrayList(); + for (Composite deployableComposite : contribution.getDeployables()) { + Composite resolvedDeployable = + contribution.getModelResolver().resolveModel(Composite.class, deployableComposite); + + resolvedDeployables.add(resolvedDeployable); + } + contribution.getDeployables().clear(); + contribution.getDeployables().addAll(resolvedDeployables); + } + + private boolean isSCADefnsFile(URI uri) { + int index = uri.toString().lastIndexOf("/"); + + index = (index != -1) ? index + 1 : 0; + + return uri.toString().substring(index).equals("definitions.xml"); + } +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.java new file mode 100644 index 0000000000..956251b2f6 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.service.impl; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.PackageType; +import org.apache.tuscany.sca.contribution.service.TypeDescriber; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; + +/** + * Implementation of the content describer for contribution packages + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +public class PackageTypeDescriberImpl implements TypeDescriber { + private final Map contentTypeRegistry = new HashMap(); + + public PackageTypeDescriberImpl() { + super(); + init(); + } + + /** + * Initialize contentType registry with know types based on known file extensions + */ + private void init() { + contentTypeRegistry.put("JAR", PackageType.JAR); + contentTypeRegistry.put("WAR", PackageType.JAR); + } + + protected String resolveContentyTypeByExtension(URL resourceURL) { + String artifactExtension = FileHelper.getExtension(resourceURL.getPath()); + if (artifactExtension == null) { + return null; + } + return contentTypeRegistry.get(artifactExtension.toUpperCase()); + } + + /** + * Build contentType for a specific resource. We first check if the file is a supported one + * (looking into our registry based on resource extension) If not found, we try to check file + * contentType Or we return defaultContentType provided + * + * @param resourceURL The artifact URL + * @param defaultContentType The default content type if we can't find the correct one + * @return The content type + */ + public String getType(URL resourceURL, String defaultContentType) { + URLConnection connection = null; + String contentType = defaultContentType; + final String urlProtocol = resourceURL.getProtocol(); + + if (urlProtocol.equals("file")) { + final File fileOrDir = FileHelper.toFile(resourceURL); + // Allow privileged access to test file. Requires FilePermissions in security policy. + Boolean isDirectory = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return fileOrDir.isDirectory(); + } + }); + if (isDirectory) { + // Special case : contribution is a folder + contentType = PackageType.FOLDER; + } + String fileName = resourceURL.toString(); + String fileExt = fileName.substring(fileName.lastIndexOf('.')+1, fileName.length()); + if ( fileExt.equalsIgnoreCase( "JAR" ) ) + return PackageType.JAR; + } else if (urlProtocol.equals("bundle") || urlProtocol.equals("bundleresource")) { + contentType = PackageType.BUNDLE; + } else { + contentType = resolveContentyTypeByExtension(resourceURL); + if (contentType == null) { + try { + connection = resourceURL.openConnection(); + connection.setUseCaches(false); + contentType = connection.getContentType(); + + if (contentType == null || contentType.equals("content/unknown")) { + // here we couldn't figure out from our registry or from URL and it's not a + // special file + // return defaultContentType if provided + contentType = defaultContentType; + } + } catch (IOException io) { + // could not access artifact, just ignore and we will return + // null contentType + } + } + } + return contentType == null ? defaultContentType : contentType; + } + +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/FileHelper.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/FileHelper.java new file mode 100644 index 0000000000..0ee8cd6aac --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/FileHelper.java @@ -0,0 +1,701 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.service.util; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.regex.Pattern; + +public class FileHelper { + /** + * The extension separator character. + */ + private static final char EXTENSION_SEPARATOR = '.'; + + /** + * The Unix separator character. + */ + private static final char UNIX_SEPARATOR = '/'; + + /** + * The Windows separator character. + */ + private static final char WINDOWS_SEPARATOR = '\\'; + + /** + * Returns the index of the last directory separator character. + *

+ * This method will handle a file in either Unix or Windows format. The + * position of the last forward or backslash is returned. + *

+ * The output will be the same irrespective of the machine that the code is + * running on. + * + * @param filename the filename to find the last path separator in, null + * returns -1 + * @return the index of the last separator character, or -1 if there is no + * such character + */ + public static int indexOfLastSeparator(String filename) { + if (filename == null) { + return -1; + } + int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR); + int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR); + return Math.max(lastUnixPos, lastWindowsPos); + } + + /** + * Returns the index of the last extension separator character, which is a + * dot. + *

+ * This method also checks that there is no directory separator after the + * last dot. To do this it uses {@link #indexOfLastSeparator(String)} which + * will handle a file in either Unix or Windows format. + *

+ * The output will be the same irrespective of the machine that the code is + * running on. + * + * @param filename the filename to find the last path separator in, null + * returns -1 + * @return the index of the last separator character, or -1 if there is no + * such character + */ + public static int indexOfExtension(String filename) { + if (filename == null) { + return -1; + } + int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR); + int lastSeparator = indexOfLastSeparator(filename); + return lastSeparator > extensionPos ? -1 : extensionPos; + } + + /** + * Gets the name minus the path from a full filename. + *

+ * This method will handle a file in either Unix or Windows format. The text + * after the last forward or backslash is returned. + * + *

+     * a/b/c.txt --> c.txt
+     * a.txt     --> a.txt
+     * a/b/c     --> c
+     * a/b/c/    --> ""
+     * 
+ * + *

+ * The output will be the same irrespective of the machine that the code is + * running on. + * + * @param fileName the filename to query, null returns null + * @return the name of the file without the path, or an empty string if none + * exists + */ + public static String getName(String fileName) { + if (fileName == null) { + return null; + } + int index = indexOfLastSeparator(fileName); + return fileName.substring(index + 1); + } + + /** + * Gets the extension of a filename. + *

+ * This method returns the textual part of the filename after the last dot. + * There must be no directory separator after the dot. + * + *

+     * foo.txt      --> "txt"
+     * a/b/c.jpg    --> "jpg"
+     * a/b.txt/c    --> ""
+     * a/b/c        --> ""
+     * 
+ * + *

+ * The output will be the same irrespective of the machine that the code is + * running on. + * + * @param filename the filename to retrieve the extension of. + * @return the extension of the file or an empty string if none exists. + */ + public static String getExtension(String filename) { + if (filename == null) { + return null; + } + int index = indexOfExtension(filename); + if (index == -1) { + return ""; + } else { + return filename.substring(index + 1); + } + } + + /** + * Make a directory, including any necessary but nonexistent parent + * directories. If there already exists a file with specified name or the + * directory cannot be created then an exception is thrown. + * + * @param directory directory to create, not null + * @throws NullPointerException if the directory is null + * @throws IOException if the directory cannot be created + */ + public static void forceMkdir(File directory) throws IOException { + if (directory.exists()) { + if (directory.isFile()) { + String message = + "File " + directory + " exists and is " + "not a directory. Unable to create directory."; + throw new IOException(message); + } + } else { + if (!directory.mkdirs()) { + String message = "Unable to create directory " + directory; + throw new IOException(message); + } + } + } + + /** + * Delete a file. If file is a directory, delete it and all sub-directories. + *

+ * The difference between File.delete() and this method are: + *

    + *
  • A directory to be deleted does not have to be empty.
  • + *
  • You get exceptions when a file or directory cannot be deleted. + * (java.io.File methods returns a boolean)
  • + *
+ * + * @param file file or directory to delete, not null + * @throws NullPointerException if the directory is null + * @throws IOException in case deletion is unsuccessful + */ + public static void forceDelete(File file) throws IOException { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + if (!file.exists()) { + throw new FileNotFoundException("File does not exist: " + file); + } + if (!file.delete()) { + String message = "Unable to delete file: " + file; + throw new IOException(message); + } + } + } + + /** + * Convert from a URL to a File. + *

+ * From version 1.1 this method will decode the URL. Syntax such as + * file:///my%20docs/file.txt will be correctly decoded to + * /my docs/file.txt. + * + * @param url the file URL to convert, null returns null + * @return the equivalent File object, or null + * if the URL's protocol is not file + * @throws IllegalArgumentException if the file is incorrectly encoded + */ + public static File toFile(URL url) { + if (url == null || !url.getProtocol().equals("file")) { + return null; + } else { + String filename = url.getFile().replace('/', File.separatorChar); + int pos = 0; + while ((pos = filename.indexOf('%', pos)) >= 0) { // NOPMD + if (pos + 2 < filename.length()) { + String hexStr = filename.substring(pos + 1, pos + 3); + char ch = (char)Integer.parseInt(hexStr, 16); + filename = filename.substring(0, pos) + ch + filename.substring(pos + 3); + } + } + return new File(filename); + } + } + + public static FileFilter getFileFilter(String regExp, boolean ignoreCase) { + return new RegExpFilter(regExp, ignoreCase); + } + + /** + * A regular-expression based resource filter + */ + public static class RegExpFilter implements FileFilter { + private Pattern pattern; + + public RegExpFilter(Pattern pattern) { + this.pattern = pattern; + } + + public RegExpFilter(String patternStr, boolean ignoreCase) { + this.pattern = Pattern.compile(patternStr, ignoreCase ? Pattern.CASE_INSENSITIVE : 0); + } + + public boolean accept(File file) { + return pattern.matcher(file.getName()).matches(); + } + + /** + * Convert wildcard into a regex pattern + * + * @param str + * @return + */ + public static RegExpFilter getWildcardFilter(String str, boolean ignoreCase) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch == '?') { + buffer.append('.'); + } else if (ch == '*') { + buffer.append(".*"); + } else { + buffer.append(ch); + } + } + return new RegExpFilter(buffer.toString(), ignoreCase); + } + + } + + /** + * Clean a directory without deleting it. + * + * @param directory directory to clean + * @throws IOException in case cleaning is unsuccessful + */ + public static void cleanDirectory(File directory) throws IOException { + if (!directory.exists()) { + String message = directory + " does not exist"; + throw new IllegalArgumentException(message); + } + + if (!directory.isDirectory()) { + String message = directory + " is not a directory"; + throw new IllegalArgumentException(message); + } + + File[] files = directory.listFiles(); + if (files == null) { // null if security restricted + throw new IOException("Failed to list contents of " + directory); + } + + IOException exception = null; + for (int i = 0; i < files.length; i++) { + File file = files[i]; + try { + forceDelete(file); + } catch (IOException ioe) { + exception = ioe; + } + } + + if (null != exception) { + throw exception; + } + } + + /** + * Clean a directory without deleting it. + * + * @param directory directory to clean, must not be null + * @throws NullPointerException if the directory is null + * @throws IOException in case cleaning is unsuccessful + */ + private static void cleanDirectoryOnExit(File directory) throws IOException { + if (!directory.exists()) { + String message = directory + " does not exist"; + throw new IllegalArgumentException(message); + } + + if (!directory.isDirectory()) { + String message = directory + " is not a directory"; + throw new IllegalArgumentException(message); + } + + File[] files = directory.listFiles(); + if (files == null) { // null if security restricted + throw new IOException("Failed to list contents of " + directory); + } + + IOException exception = null; + for (int i = 0; i < files.length; i++) { + File file = files[i]; + try { + forceDeleteOnExit(file); + } catch (IOException ioe) { + exception = ioe; + } + } + + if (null != exception) { + throw exception; + } + } + + /** + * Copies a whole directory to a new location preserving the file dates. + *

+ * This method copies the specified directory and all its child directories + * and files to the specified destination. The destination is the new + * location and name of the directory. + *

+ * The destination directory is created if it does not exist. If the + * destination directory did exist, then this method merges the source with + * the destination, with the source taking precedence. + * + * @param srcDir an existing directory to copy, must not be + * null + * @param destDir the new directory, must not be null + * @throws NullPointerException if source or destination is + * null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @since Commons IO 1.1 + */ + public static void copyDirectory(File srcDir, File destDir) throws IOException { + copyDirectory(srcDir, destDir, true); + } + + /** + * Copies a whole directory to a new location. + *

+ * This method copies the contents of the specified source directory to + * within the specified destination directory. + *

+ * The destination directory is created if it does not exist. If the + * destination directory did exist, then this method merges the source with + * the destination, with the source taking precedence. + * + * @param srcDir an existing directory to copy, must not be + * null + * @param destDir the new directory, must not be null + * @param preserveFileDate true if the file date of the copy should be the + * same as the original + * @throws NullPointerException if source or destination is + * null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @since Commons IO 1.1 + */ + public static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate) throws IOException { + if (srcDir == null) { + throw new NullPointerException("Source must not be null"); + } + if (destDir == null) { + throw new NullPointerException("Destination must not be null"); + } + if (!srcDir.exists()) { + throw new FileNotFoundException("Source '" + srcDir + "' does not exist"); + } + if (!srcDir.isDirectory()) { + throw new IOException("Source '" + srcDir + "' exists but is not a directory"); + } + if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) { + throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same"); + } + doCopyDirectory(srcDir, destDir, preserveFileDate); + } + + // ----------------------------------------------------------------------- + /** + * Copies a directory to within another directory preserving the file dates. + *

+ * This method copies the source directory and all its contents to a + * directory of the same name in the specified destination directory. + *

+ * The destination directory is created if it does not exist. If the + * destination directory did exist, then this method merges the source with + * the destination, with the source taking precedence. + * + * @param srcDir an existing directory to copy, must not be + * null + * @param destDir the directory to place the copy in, must not be + * null + * @throws NullPointerException if source or destination is + * null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @since Commons IO 1.2 + */ + public static void copyDirectoryToDirectory(File srcDir, File destDir) throws IOException { + if (srcDir == null) { + throw new NullPointerException("Source must not be null"); + } + if (!(srcDir.exists() && srcDir.isDirectory())) { + throw new IllegalArgumentException("Source '" + destDir + "' is not a directory"); + } + if (destDir == null) { + throw new NullPointerException("Destination must not be null"); + } + if (!(destDir.exists() && destDir.isDirectory())) { + throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory"); + } + copyDirectory(srcDir, new File(destDir, srcDir.getName()), true); + } + + /** + * Copies a file to a new location preserving the file date. + *

+ * This method copies the contents of the specified source file to the + * specified destination file. The directory holding the destination file is + * created if it does not exist. If the destination file exists, then this + * method will overwrite it. + * + * @param srcFile an existing file to copy, must not be null + * @param destFile the new file, must not be null + * @throws NullPointerException if source or destination is + * null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @see #copyFileToDirectory(File, File) + */ + public static void copyFile(File srcFile, File destFile) throws IOException { + copyFile(srcFile, destFile, true); + } + + /** + * Copies a file to a new location. + *

+ * This method copies the contents of the specified source file to the + * specified destination file. The directory holding the destination file is + * created if it does not exist. If the destination file exists, then this + * method will overwrite it. + * + * @param srcFile an existing file to copy, must not be null + * @param destFile the new file, must not be null + * @param preserveFileDate true if the file date of the copy should be the + * same as the original + * @throws NullPointerException if source or destination is + * null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @see #copyFileToDirectory(File, File, boolean) + */ + public static void copyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { + if (srcFile == null) { + throw new NullPointerException("Source must not be null"); + } + if (destFile == null) { + throw new NullPointerException("Destination must not be null"); + } + if (!srcFile.exists()) { + throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); + } + if (srcFile.isDirectory()) { + throw new IOException("Source '" + srcFile + "' exists but is a directory"); + } + if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) { + throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same"); + } + if (!(destFile.getParentFile() != null && destFile.getParentFile().exists())) { + if (!destFile.getParentFile().mkdirs()) { //NOPMD + throw new IOException("Destination '" + destFile + "' directory cannot be created"); + } + } + if (!(destFile.exists() && destFile.canWrite())) { + throw new IOException("Destination '" + destFile + "' exists but is read-only"); + } + doCopyFile(srcFile, destFile, preserveFileDate); + } + + // ----------------------------------------------------------------------- + /** + * Copies a file to a directory preserving the file date. + *

+ * This method copies the contents of the specified source file to a file of + * the same name in the specified destination directory. The destination + * directory is created if it does not exist. If the destination file + * exists, then this method will overwrite it. + * + * @param srcFile an existing file to copy, must not be null + * @param destDir the directory to place the copy in, must not be + * null + * @throws NullPointerException if source or destination is null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @see #copyFile(File, File, boolean) + */ + public static void copyFileToDirectory(File srcFile, File destDir) throws IOException { + copyFileToDirectory(srcFile, destDir, true); + } + + /** + * Copies a file to a directory optionally preserving the file date. + *

+ * This method copies the contents of the specified source file to a file of + * the same name in the specified destination directory. The destination + * directory is created if it does not exist. If the destination file + * exists, then this method will overwrite it. + * + * @param srcFile an existing file to copy, must not be null + * @param destDir the directory to place the copy in, must not be + * null + * @param preserveFileDate true if the file date of the copy should be the + * same as the original + * @throws NullPointerException if source or destination is + * null + * @throws IOException if source or destination is invalid + * @throws IOException if an IO error occurs during copying + * @see #copyFile(File, File, boolean) + * @since Commons IO 1.3 + */ + public static void copyFileToDirectory(File srcFile, File destDir, boolean preserveFileDate) throws IOException { + if (destDir == null) { + throw new NullPointerException("Destination must not be null"); + } + if (!(destDir.exists() && destDir.isDirectory())) { + throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory"); + } + copyFile(srcFile, new File(destDir, srcFile.getName()), preserveFileDate); + } + + // ----------------------------------------------------------------------- + /** + * Recursively delete a directory. + * + * @param directory directory to delete + * @throws IOException in case deletion is unsuccessful + */ + public static void deleteDirectory(File directory) throws IOException { + if (!directory.exists()) { + return; + } + + cleanDirectory(directory); + if (!directory.delete()) { + String message = "Unable to delete directory " + directory + "."; + throw new IOException(message); + } + } + + /** + * Recursively schedule directory for deletion on JVM exit. + * + * @param directory directory to delete, must not be null + * @throws NullPointerException if the directory is null + * @throws IOException in case deletion is unsuccessful + */ + private static void deleteDirectoryOnExit(File directory) throws IOException { + if (!directory.exists()) { + return; + } + + cleanDirectoryOnExit(directory); + directory.deleteOnExit(); + } + + /** + * Internal copy directory method. + * + * @param srcDir the validated source directory, must not be + * null + * @param destDir the validated destination directory, must not be + * null + * @param preserveFileDate whether to preserve the file date + * @throws IOException if an error occurs + * @since Commons IO 1.1 + */ + private static void doCopyDirectory(File srcDir, File destDir, boolean preserveFileDate) throws IOException { + if (destDir.exists()) { + if (!destDir.isDirectory()) { + throw new IOException("Destination '" + destDir + "' exists but is not a directory"); + } + } else { + if (!destDir.mkdirs()) { + throw new IOException("Destination '" + destDir + "' directory cannot be created"); + } + if (preserveFileDate) { + destDir.setLastModified(srcDir.lastModified()); + } + } + if (!destDir.canWrite()) { + throw new IOException("Destination '" + destDir + "' cannot be written to"); + } + // recurse + File[] files = srcDir.listFiles(); + if (files == null) { // null if security restricted + throw new IOException("Failed to list contents of " + srcDir); + } + for (int i = 0; i < files.length; i++) { + File copiedFile = new File(destDir, files[i].getName()); + if (files[i].isDirectory()) { + doCopyDirectory(files[i], copiedFile, preserveFileDate); + } else { + doCopyFile(files[i], copiedFile, preserveFileDate); + } + } + } + + /** + * Internal copy file method. + * + * @param srcFile the validated source file, must not be null + * @param destFile the validated destination file, must not be + * null + * @param preserveFileDate whether to preserve the file date + * @throws IOException if an error occurs + */ + private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException { + if (destFile.exists() && destFile.isDirectory()) { + throw new IOException("Destination '" + destFile + "' exists but is a directory"); + } + + FileInputStream input = new FileInputStream(srcFile); + try { + FileOutputStream output = new FileOutputStream(destFile); + try { + IOHelper.copy(input, output); + } finally { + IOHelper.closeQuietly(output); + } + } finally { + IOHelper.closeQuietly(input); + } + + if (srcFile.length() != destFile.length()) { + throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'"); + } + if (preserveFileDate) { + destFile.setLastModified(srcFile.lastModified()); + } + } + + /** + * Schedule a file to be deleted when JVM exits. If file is directory delete + * it and all sub-directories. + * + * @param file file or directory to delete, must not be null + * @throws NullPointerException if the file is null + * @throws IOException in case deletion is unsuccessful + */ + public static void forceDeleteOnExit(File file) throws IOException { + if (file.isDirectory()) { + deleteDirectoryOnExit(file); + } else { + file.deleteOnExit(); + } + } + +} diff --git a/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/IOHelper.java b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/IOHelper.java new file mode 100644 index 0000000000..6cbdc87d55 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/util/IOHelper.java @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.service.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.jar.JarFile; + +public class IOHelper { + /** + * The default buffer size to use. + */ + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + /** + * Unconditionally close an InputStream. + *

+ * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + * + * @param input the InputStream to close, may be null or already closed + */ + public static void closeQuietly(InputStream input) { + try { + if (input != null) { + input.close(); + } + } catch (IOException ioe) { + // ignore + } + } + + /** + * Unconditionally close an OutputStream. + *

+ * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + * + * @param output the OutputStream to close, may be null or already closed + */ + public static void closeQuietly(OutputStream output) { + try { + if (output != null) { + output.close(); + } + } catch (IOException ioe) { + // ignore + } + } + + /** + * Copy bytes from an InputStream to an + * OutputStream. + *

+ * This method buffers the input internally, so there is no need to use a + * BufferedInputStream. + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + * @since Commons IO 1.1 + */ + public static int copy(InputStream input, OutputStream output) throws IOException { + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + int count = 0; + int n = 0; + while (-1 != (n = input.read(buffer))) { // NOPMD + output.write(buffer, 0, n); + count += n; + } + return count; + } + + public static InputStream getInputStream(URL url) throws IOException { + return new SafeURLInputStream(url); + } + + /** + * This class is a workaround for URL stream issue as illustrated below. + * InputStream is=url.getInputStream(); is.close(); // This line doesn't close + * the JAR file if the URL is a jar entry like "jar:file:/a.jar!/my.composite" We + * also need to turn off the JarFile cache. + * + * @see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4950148 + * + * @version $Rev: 641216 $ $Date: 2008-03-26 01:15:08 -0800 (Wed, 26 Mar 2008) $ + */ + public static class SafeURLInputStream extends InputStream { + private JarFile jarFile; + private InputStream is; + + public SafeURLInputStream(URL url) throws IOException { + String protocol = url.getProtocol(); + if (protocol != null && (protocol.equals("jar"))) { + JarURLConnection connection = (JarURLConnection)url.openConnection(); + // We cannot use cache + connection.setUseCaches(false); + try { + is = connection.getInputStream(); + } catch (IOException e) { + throw e; + } + jarFile = connection.getJarFile(); + } else { + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + is = connection.getInputStream(); + } + } + + public SafeURLInputStream(JarURLConnection connection) throws IOException { + // We cannot use cache + connection.setUseCaches(false); + is = connection.getInputStream(); + jarFile = connection.getJarFile(); + } + + @Override + public int available() throws IOException { + return is.available(); + } + + @Override + public void close() throws IOException { + is.close(); + // We need to close the JAR file + if (jarFile != null) { + jarFile.close(); + } + } + + @Override + public synchronized void mark(int readlimit) { + is.mark(readlimit); + } + + @Override + public boolean markSupported() { + return is.markSupported(); + } + + @Override + public int read() throws IOException { + return is.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return is.read(b, off, len); + } + + @Override + public int read(byte[] b) throws IOException { + return is.read(b); + } + + @Override + public synchronized void reset() throws IOException { + is.reset(); + } + + @Override + public long skip(long n) throws IOException { + return is.skip(n); + } + } +} \ No newline at end of file diff --git a/branches/sca-android/contribution-impl/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor b/branches/sca-android/contribution-impl/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor new file mode 100644 index 0000000000..b644709266 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor @@ -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.contribution.processor.impl.FolderContributionProcessor;type=application/vnd.tuscany.folder +org.apache.tuscany.sca.contribution.processor.impl.JarContributionProcessor;type=application/x-compressed diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/FolderContributionPackageProcessorTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/FolderContributionPackageProcessorTestCase.java new file mode 100644 index 0000000000..f2a7aa6cb9 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/FolderContributionPackageProcessorTestCase.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.processor.impl.FolderContributionProcessor; + +/** + * Folder Package Processor test case + * Verifies proper handle of File System structured contributions + * + * @version $Rev: 618718 $ $Date: 2008-02-05 09:45:08 -0800 (Tue, 05 Feb 2008) $ + */ +public class FolderContributionPackageProcessorTestCase extends TestCase { + private static final String FOLDER_CONTRIBUTION = "."; + + public final void testProcessPackageArtifacts() throws Exception { + FolderContributionProcessor folderProcessor = new FolderContributionProcessor(); + URL contributionURL = new File(FOLDER_CONTRIBUTION).toURL().toURI().toURL(); + + List artifacts = folderProcessor.getArtifacts(contributionURL, null); + assertNotNull(artifacts); + } +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/JarContributionPackageProcessorTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/JarContributionPackageProcessorTestCase.java new file mode 100644 index 0000000000..0f234e09fe --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/JarContributionPackageProcessorTestCase.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.contribution.processor; + +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.processor.impl.JarContributionProcessor; +import org.apache.tuscany.sca.contribution.service.util.IOHelper; + +/** + * JAR Package Processor test case + * Verifies proper handle of JAR Archives contributions + * + * @version $Rev: 618158 $ $Date: 2008-02-03 18:44:47 -0800 (Sun, 03 Feb 2008) $ + */ + +public class JarContributionPackageProcessorTestCase extends TestCase { + private static final String JAR_CONTRIBUTION = "/repository/sample-calculator.jar"; + + public final void testProcessPackageArtifacts() throws Exception { + JarContributionProcessor jarProcessor = new JarContributionProcessor(); + + URL jarURL = getClass().getResource(JAR_CONTRIBUTION); + InputStream jarStream = jarURL.openStream(); + List artifacts = null; + try { + artifacts = jarProcessor.getArtifacts(jarURL, jarStream); + } finally { + IOHelper.closeQuietly(jarStream); + } + + assertNotNull(artifacts); + } +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java new file mode 100644 index 0000000000..7fd9cc183a --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.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.contribution.processor; + +import java.net.URI; +import java.net.URL; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; + + +/** + * URL Artifact Processor Extension Point test case + * Verifies the right registration and lookup for processors that handle filename and file types + * + * @version $Rev: 618158 $ $Date: 2008-02-03 18:44:47 -0800 (Sun, 03 Feb 2008) $ + */ +public class URLartifactProcessorExtensionPointTestCase extends TestCase { + + private URLArtifactProcessorExtensionPoint artifactProcessors; + + @Override + protected void setUp() throws Exception { + artifactProcessors = new DefaultURLArtifactProcessorExtensionPoint(null); + artifactProcessors.addArtifactProcessor(new FileTypeArtifactProcessor()); + artifactProcessors.addArtifactProcessor(new FileNameArtifactProcessor()); + } + + + public final void testFileTypeProcessor() { + assertNotNull(artifactProcessors.getProcessor(".m1")); + } + + + public final void testFileNameProcessor() { + assertNotNull(artifactProcessors.getProcessor("file.m2")); + + } + + /** + * Internal mock classes + * + */ + + private class M1 { + } + + private class M2 { + } + + private class FileTypeArtifactProcessor implements URLArtifactProcessor { + public FileTypeArtifactProcessor() { + } + + public M1 read(URL contributionURL, URI uri, URL url) throws ContributionReadException { + return null; + } + + public void resolve(M1 m1, ModelResolver resolver) throws ContributionResolveException { + } + + public String getArtifactType() { + return ".m1"; + } + + public Class getModelType() { + return M1.class; + } + } + + private class FileNameArtifactProcessor implements URLArtifactProcessor { + public FileNameArtifactProcessor() { + } + + public M2 read(URL contributionURL, URI uri, URL url) throws ContributionReadException { + return null; + } + + public void resolve(M2 m2, ModelResolver resolver) throws ContributionResolveException { + } + + public String getArtifactType() { + return "file.m2"; + } + + public Class getModelType() { + return M2.class; + } + } + +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java new file mode 100644 index 0000000000..ea157489f6 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.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.contribution.resolver; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; + +/** + * Test the default model resolver implementation. + * + * @version $Rev: 631808 $ $Date: 2008-02-27 17:49:26 -0800 (Wed, 27 Feb 2008) $ + */ +public class DefaultModelResolverTestCase extends TestCase { + + private ModelResolver resolver; + private ContributionFactory factory; + + @Override + protected void setUp() throws Exception { + resolver = new DefaultModelResolver(); + factory = new DefaultContributionFactory(); + } + + public void testResolved() { + Model a = new Model("a"); + resolver.addModel(a); + Model x = new Model("a"); + x = resolver.resolveModel(Model.class, x); + assertTrue(x == a); + } + + public void testUnresolved() { + Model x = new Model("a"); + Model y = resolver.resolveModel(Model.class, x); + assertTrue(x == y); + } + + public void testResolvedArtifact() { + Artifact artifact = factory.createArtifact(); + artifact.setURI("foo/bar"); + resolver.addModel(artifact); + Artifact x = factory.createArtifact(); + x.setURI("foo/bar"); + x = resolver.resolveModel(Artifact.class, x); + assertTrue(x == artifact); + } + + class Model { + private String name; + + Model(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return name.equals(((Model)obj).name); + } + } + +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java new file mode 100644 index 0000000000..a180d11adb --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java @@ -0,0 +1,126 @@ + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; + +/** + * Test DefaultArtifactResolver. + * + * @version $Rev: 618158 $ $Date: 2008-02-03 18:44:47 -0800 (Sun, 03 Feb 2008) $ + */ +public class ExtensibleModelResolverTestCase extends TestCase { + private ExtensibleModelResolver resolver; + + private ContributionFactory factory; + + @Override + protected void setUp() throws Exception { + + ModelResolverExtensionPoint resolvers = new DefaultModelResolverExtensionPoint(); + resolvers.addResolver(Model.class, TestModelResolver.class); + + ModelFactoryExtensionPoint factories = new DefaultModelFactoryExtensionPoint(); + + resolver = new ExtensibleModelResolver(null, resolvers, factories, null); + + factory = new DefaultContributionFactory(); + } + + public void testResolvedDefault() { + OtherModel a = new OtherModel("a"); + resolver.addModel(a); + OtherModel x = new OtherModel("a"); + x = resolver.resolveModel(OtherModel.class, x); + assertTrue(x == a); + } + + public void testResolvedRegisteredClass() { + Model a = new Model("a"); + resolver.addModel(a); + Model x = new Model("a"); + x = resolver.resolveModel(Model.class, x); + assertTrue(x == a); + } + + public void testUnresolvedDefault() { + OtherModel x = new OtherModel("a"); + OtherModel y = resolver.resolveModel(OtherModel.class, x); + assertTrue(x == y); + } + + public void testUnresolved() { + Model x = new Model("a"); + Model y = resolver.resolveModel(Model.class, x); + assertTrue(x == y); + } + + public void testResolvedArtifact() { + Artifact artifact = factory.createArtifact(); + artifact.setURI("foo/bar"); + resolver.addModel(artifact); + Artifact x = factory.createArtifact(); + x.setURI("foo/bar"); + x = resolver.resolveModel(Artifact.class, x); + assertTrue(x == artifact); + } + + private class Model { + private String name; + + Model(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return name.equals(((Model)obj).name); + } + } + + private class OtherModel { + private String name; + + OtherModel(String name) { + this.name = name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return name.equals(((OtherModel)obj).name); + } + } +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java new file mode 100644 index 0000000000..c60bcaa0cc --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; + +/** + * A test implementation of a model resolver, based on a map. + * + * @version $Rev: 618158 $ $Date: 2008-02-03 18:44:47 -0800 (Sun, 03 Feb 2008) $ + */ +public class TestModelResolver implements ModelResolver { + + private Map map = new HashMap(); + + public TestModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) { + } + + public T resolveModel(Class modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + // Return the resolved object + return modelClass.cast(resolved); + } + // Return the unresolved object + return unresolved; + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved) { + return map.remove(resolved); + } + +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/ContributionRepositoryTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/ContributionRepositoryTestCase.java new file mode 100644 index 0000000000..6d33db5810 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/ContributionRepositoryTestCase.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.services; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; + +import javax.xml.stream.XMLInputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.service.impl.ContributionRepositoryImpl; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; + +public class ContributionRepositoryTestCase extends TestCase { + private ContributionRepositoryImpl repository; + + @Override + protected void setUp() throws Exception { + // create repository (this should re-create the root directory) + this.repository = new ContributionRepositoryImpl("target/repository/", XMLInputFactory.newInstance()); + repository.init(); + } + + public void testStore() throws Exception { + String resourceLocation = "/repository/sample-calculator.jar"; + String contribution = "sample-calculator.jar"; + URL contributionLocation = getClass().getResource(resourceLocation); + InputStream contributionStream = getClass().getResourceAsStream(resourceLocation); + repository.store(contribution, contributionLocation, contributionStream); + + URL contributionURL = repository.find(contribution); + assertNotNull(contributionURL); + } + + public void testRemove() throws Exception { + String resourceLocation = "/repository/sample-calculator.jar"; + String contribution = "sample-calculator.jar"; + URL contributionLocation = getClass().getResource(resourceLocation); + InputStream contributionStream = getClass().getResourceAsStream(resourceLocation); + repository.store(contribution, contributionLocation, contributionStream); + + repository.remove(contribution); + URL contributionURL = repository.find(contribution); + assertNull(contributionURL); + } + + public void testList() throws Exception { + String resourceLocation = "/repository/sample-calculator.jar"; + String contribution = "sample-calculator.jar"; + URL contributionLocation = getClass().getResource(resourceLocation); + InputStream contributionStream = getClass().getResourceAsStream(resourceLocation); + repository.store(contribution, contributionLocation, contributionStream); + + assertEquals(1, repository.list().size()); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + FileHelper.deleteDirectory(new File("target/repository")); + } +} diff --git a/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/PackageTypeDescriberImplTestCase.java b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/PackageTypeDescriberImplTestCase.java new file mode 100644 index 0000000000..124a3a8b1b --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/java/org/apache/tuscany/sca/contribution/services/PackageTypeDescriberImplTestCase.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.contribution.services; + +import java.net.URL; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.PackageType; +import org.apache.tuscany.sca.contribution.service.impl.PackageTypeDescriberImpl; + +public class PackageTypeDescriberImplTestCase extends TestCase { + private PackageTypeDescriberImpl packageTypeDescriber; + + public void testResolveArchivePackageType() throws Exception { + URL artifactURL = getClass().getResource("/deployables/sample-calculator.jar"); + assertEquals(PackageType.JAR, this.packageTypeDescriber.getType(artifactURL, null)); + } + + public void testResolveFolderPackageType() throws Exception { + URL artifactURL = getClass().getResource("/deployables/"); + assertEquals(PackageType.FOLDER, this.packageTypeDescriber.getType(artifactURL, null)); + } + + public void testResolveFolder2PackageType() throws Exception { + URL artifactURL = getClass().getResource("/deployables"); + assertEquals(PackageType.FOLDER, this.packageTypeDescriber.getType(artifactURL, null)); + } + + + public void testResolveUnknownPackageType() throws Exception { + URL artifactURL = getClass().getResource("/test.ext"); + assertNull(this.packageTypeDescriber.getType(artifactURL, null)); + } + + public void testDefaultPackageType() throws Exception { + URL artifactURL = getClass().getResource("/test.ext"); + assertEquals("application/vnd.tuscany.ext", + packageTypeDescriber.getType(artifactURL, "application/vnd.tuscany.ext")); + } + + @Override + protected void setUp() throws Exception { + packageTypeDescriber = new PackageTypeDescriberImpl(); + } + +} diff --git a/branches/sca-android/contribution-impl/src/test/resources/deployables/sample-calculator.jar b/branches/sca-android/contribution-impl/src/test/resources/deployables/sample-calculator.jar new file mode 100644 index 0000000000..0ca3a1b781 Binary files /dev/null and b/branches/sca-android/contribution-impl/src/test/resources/deployables/sample-calculator.jar differ diff --git a/branches/sca-android/contribution-impl/src/test/resources/repository/sample-calculator.jar b/branches/sca-android/contribution-impl/src/test/resources/repository/sample-calculator.jar new file mode 100644 index 0000000000..9c46c679d2 Binary files /dev/null and b/branches/sca-android/contribution-impl/src/test/resources/repository/sample-calculator.jar differ diff --git a/branches/sca-android/contribution-impl/src/test/resources/test.composite b/branches/sca-android/contribution-impl/src/test/resources/test.composite new file mode 100644 index 0000000000..1e09549194 --- /dev/null +++ b/branches/sca-android/contribution-impl/src/test/resources/test.composite @@ -0,0 +1,22 @@ + + + + This file just needs to exist + \ No newline at end of file diff --git a/branches/sca-android/contribution-impl/src/test/resources/test.ext b/branches/sca-android/contribution-impl/src/test/resources/test.ext new file mode 100644 index 0000000000..e69de29bb2 diff --git a/branches/sca-android/contribution/.classpath b/branches/sca-android/contribution/.classpath new file mode 100644 index 0000000000..732ae371c2 --- /dev/null +++ b/branches/sca-android/contribution/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/contribution/.project b/branches/sca-android/contribution/.project new file mode 100644 index 0000000000..24cbaf4abb --- /dev/null +++ b/branches/sca-android/contribution/.project @@ -0,0 +1,19 @@ + + tuscany-contribution + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/contribution/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/contribution/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..8fc9b863cf --- /dev/null +++ b/branches/sca-android/contribution/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:19:33 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/contribution/DISCLAIMER b/branches/sca-android/contribution/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/contribution/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/contribution/LICENSE b/branches/sca-android/contribution/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/contribution/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/branches/sca-android/contribution/NOTICE b/branches/sca-android/contribution/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/contribution/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/contribution/pom.xml b/branches/sca-android/contribution/pom.xml new file mode 100644 index 0000000000..a09a28bd5d --- /dev/null +++ b/branches/sca-android/contribution/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-contribution + Apache Tuscany SCA Contribution Model + + + + org.apache.tuscany.sca + tuscany-assembly + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-extensibility + 2.0-incubating-SNAPSHOT + + + + stax + stax-api + 1.0.1 + + + xml-apis + xml-apis + 1.3.03 + + + diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java new file mode 100644 index 0000000000..ad2dbace5e --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.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.contribution; + +import org.apache.tuscany.sca.assembly.Base; + + +/** + * Represents an artifact in an SCA contribution. + * + * @version $Rev: 618930 $ $Date: 2008-02-06 01:15:49 -0800 (Wed, 06 Feb 2008) $ + */ +public interface Artifact extends Base { + + /** + * Returns the URI that unique identifies the artifact inside the contribution. + * + * @return The artifact URI + */ + String getURI(); + + /** + * Sets the URI that uniquely identifies the artifact inside the contribution. + * + * @param uri The artifact URI + */ + void setURI(String uri); + + /** + * Returns the location of the artifact. + * + * @return The artifact location + */ + String getLocation(); + + /** + * Set the location of the artifact. + * + * @param location The artifact location + */ + void setLocation(String location); + + + /** + * Returns the in-memory model representing the artifact. + * + * @return The model object + */ + Object getModel(); + + /** + * Sets the in-memory model representing the artifact. + * + * @param model The model object + */ + void setModel(Object model); + + /** + * Returns the contents of the artifact cached here. + * @return the contents of the artifact + */ + byte[] getContents(); + + /** + * Sets the contents of the artifact. + * @param contents the contents of the artifact + */ + void setContents(byte[] contents); +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java new file mode 100644 index 0000000000..f3d2b62fc1 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.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.contribution; + +/** + * Constants for the main supported contribution package type. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +@Deprecated +public interface ContentType { + + /** + * Java compressed contribution package + */ + String JAR = "application/x-compressed"; + + /** + * Filesystem folder contribution package + */ + String FOLDER = "application/vnd.tuscany.folder"; + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java new file mode 100644 index 0000000000..1bc4cc7b9e --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an SCA contribution. + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public interface Contribution extends Artifact { + + /** + * Default location of contribution metadata in an SCA contribution. + */ + String SCA_CONTRIBUTION_META = "META-INF/sca-contribution.xml"; + + /** + * Default location of a generated contribution metadata in an SCA contribution. + */ + String SCA_CONTRIBUTION_GENERATED_META = "META-INF/sca-contribution-generated.xml"; + + /** + * Default location of deployable composites in an SCA contribution. + */ + String SCA_CONTRIBUTION_DEPLOYABLES = "META-INF/sca-deployables/"; + + + /** + * Returns a list of exports based on the contribution metadata. + * + * @return The list of exports in this contribution + */ + List getExports(); + + /** + * Returns a list of imports based on the contribution metadata. + * + * @return The list of imports in this contribution + */ + List getImports(); + + /** + * Returns the list of deployable composites in the contribution. + * + * @return The list of deployable composites + */ + List getDeployables(); + + /** + * Returns the list of artifacts in the contribution. + * + * @return The list of artifacts in the contribution + */ + List getArtifacts(); + + /** + * Returns the model resolver for the models representing the artifacts + * visible in the scope of this contribution. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing the artifacts + * visible in the scope of this contribution. + * + * @param modelResolver The model resolver + */ + void setModelResolver(ModelResolver modelResolver); + + /** + * Returns the ClassLoader used to load classes and resources from + * this contribution + * + * FIXME Remove this, the base contribution model should not depend + * on Java ClassLoaders. + * + * @return The contribution ClassLoader + */ + ClassLoader getClassLoader(); + + /** + * Sets the ClassLoader used to load classes and resources from + * this contribution + * + * FIXME Remove this, the base contribution model should not depend + * on Java ClassLoaders. + * + * @param classLoader the contribution class loader + */ + void setClassLoader(ClassLoader classLoader); + +} \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java new file mode 100644 index 0000000000..31fccb6f4c --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution; + + +/** + * A factory for the contribution model. + * + * @version $Rev: 629585 $ $Date: 2008-02-20 11:39:27 -0800 (Wed, 20 Feb 2008) $ + */ +public interface ContributionFactory { + + /** + * Create a contribution model object + * + * @return The new contribution model object + */ + Contribution createContribution(); + + /** + * Create a deployedArtifact model object + * + * @return The new deployedArtifact model object + */ + @Deprecated + DeployedArtifact createDeployedArtifact(); + + /** + * Create an artifact model object + * + * @return The new artifact model object + */ + Artifact createArtifact(); + +} \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java new file mode 100644 index 0000000000..73df82b8b5 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.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.contribution; + +import org.apache.tuscany.sca.contribution.impl.ContributionFactoryImpl; + + +/** + * Default implementation of a contribution model factory. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public class DefaultContributionFactory extends ContributionFactoryImpl { + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java new file mode 100644 index 0000000000..7d56f37472 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.HashMap; + +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + + +/** + * Default implementation of a model factory extension point. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultModelFactoryExtensionPoint implements ModelFactoryExtensionPoint { + + private HashMap, Object> factories = new HashMap, Object>(); + + /** + * Constructs a new DefaultModelFactoryExtensionPoint. + */ + public DefaultModelFactoryExtensionPoint() { + } + + /** + * Add a model factory extension. + * + * @param factory The factory to add + */ + public void addFactory(Object factory) { + Class[] interfaces = factory.getClass().getInterfaces(); + if (interfaces.length == 0) { + Class sc = factory.getClass().getSuperclass(); + if (sc != Object.class) { + factories.put(sc, factory); + } + } else { + for (int i = 0; i[] interfaces = factory.getClass().getInterfaces(); + if (interfaces.length == 0) { + Class sc = factory.getClass().getSuperclass(); + if (sc != Object.class) { + factories.remove(sc); + } + } else { + for (int i = 0; i T getFactory(Class factoryInterface) { + Object factory = factories.get(factoryInterface); + if (factory == null) { + + if (factoryInterface.isInterface()) { + + // Dynamically load a factory class declared under META-INF/services + try { + Class factoryClass = ServiceDiscovery.getInstance().loadFirstServiceClass(factoryInterface); + if (factoryClass != null) { + + try { + // Default empty constructor + Constructor constructor = factoryClass.getConstructor(); + factory = constructor.newInstance(); + } catch (NoSuchMethodException e) { + + // Constructor taking the model factory extension point + Constructor constructor = factoryClass.getConstructor(ModelFactoryExtensionPoint.class); + factory = constructor.newInstance(this); + } + + // Cache the loaded factory + addFactory(factory); + } + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } else { + + // Call the newInstance static method on the factory abstract class + try { + Method newInstanceMethod = factoryInterface.getMethod("newInstance"); + factory = newInstanceMethod.invoke(null); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + + // Cache the factory + addFactory(factory); + } + } + return factoryInterface.cast(factory); + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java new file mode 100644 index 0000000000..3cde4788d7 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution; + +/** + * Representation of a deployed artifact + * + * @version $Rev: 615632 $ $Date: 2008-01-27 11:14:25 -0800 (Sun, 27 Jan 2008) $ + */ +@Deprecated +public interface DeployedArtifact extends Artifact { +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java new file mode 100644 index 0000000000..43d2b54a3d --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.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.contribution; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of an export. + * + * @version $Rev: 615632 $ $Date: 2008-01-27 11:14:25 -0800 (Sun, 27 Jan 2008) $ + */ +public interface Export { + + /** + * Returns the model resolver for the models representing artifacts + * made available by this export. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing artifacts + * made available by this export. + * + * @param modelResolver + */ + void setModelResolver(ModelResolver modelResolver); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java new file mode 100644 index 0000000000..1f60ba8073 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * The representation of an import. + * + * @version $Rev: 631778 $ $Date: 2008-02-27 15:54:38 -0800 (Wed, 27 Feb 2008) $ + */ +public interface Import { + + /** + * Returns the model resolver for the models representing artifacts + * made available by this import. + * + * @return The model resolver + */ + ModelResolver getModelResolver(); + + /** + * Sets the model resolver for the models representing artifacts + * made available by this import. + * + * @param modelResolver The model resolver + */ + void setModelResolver(ModelResolver modelResolver); + + /** + * Verify that a specific export actually exports what is being imported. + * + * @param export The Exported being verified + * @return true/false + */ + boolean match(Export export); + +} \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java new file mode 100644 index 0000000000..96decab6da --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.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.contribution; + +/** + * An extension point for model factories. Model factories are provided to + * abstract the classes that represent artifacts in the assembly model away + * from their creation mechanism. When the runtime needs to extend the model + * as it reads in contributed artifacts it looks up the factory for the + * artifact required in this registry + * + * @version $Rev: 562796 $ $Date: 2007-08-04 18:20:28 -0700 (Sat, 04 Aug 2007) $ + */ +public interface ModelFactoryExtensionPoint { + + /** + * Add a model factory extension. + * + * @param factory The factory to add + */ + void addFactory(Object factory); + + /** + * Remove a model factory extension. + * + * @param factory The factory to remove + */ + void removeFactory(Object factory); + + /** + * Get a factory implementing the given interface. + * @param factoryInterface the lookup key (factory interface) + * @return The factory + */ + T getFactory(Class factoryInterface); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java new file mode 100644 index 0000000000..f1e7147959 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution; + +/** + * Constants for the main supported contribution package types. + * + * @version $Rev: 637139 $ $Date: 2008-03-14 09:02:49 -0700 (Fri, 14 Mar 2008) $ + */ +public interface PackageType { + + /** + * Java compressed contribution package + */ + String JAR = "application/x-compressed"; + + /** + * Filesystem folder contribution package + */ + String FOLDER = "application/vnd.tuscany.folder"; + + + String BUNDLE = "application/osgi.bundle"; + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java new file mode 100644 index 0000000000..43a6586815 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import org.apache.tuscany.sca.contribution.Artifact; + + +/** + * The model representing an artifact in a contribution. + * + * @version $Rev: 632520 $ $Date: 2008-02-29 16:58:53 -0800 (Fri, 29 Feb 2008) $ + */ +class ArtifactImpl implements Artifact { + private String uri; + private String location; + private Object model; + private boolean unresolved; + private byte[] contents; + + ArtifactImpl() { + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public Object getModel() { + return model; + } + + public void setModel(Object model) { + this.model = model; + } + + public byte[] getContents() { + return contents; + } + + public void setContents(byte[] contents) { + this.contents = contents; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean unresolved) { + this.unresolved = unresolved; + } + + @Override + public int hashCode() { + return uri.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof Artifact) { + return uri.equals(((Artifact)obj).getURI()); + } else { + return false; + } + } + } + + @Override + public String toString() { + return "Artifact:" + uri + "\n" + + "at: " + location; + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java new file mode 100644 index 0000000000..c545fd6e08 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.impl; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DeployedArtifact; + + +/** + * Default implementation of a contribution model factory. + * + * @version $Rev: 629585 $ $Date: 2008-02-20 11:39:27 -0800 (Wed, 20 Feb 2008) $ + */ +public class ContributionFactoryImpl implements ContributionFactory { + + public ContributionFactoryImpl() { + } + + public Contribution createContribution() { + return new ContributionImpl(); + } + + public Artifact createArtifact() { + return new ArtifactImpl(); + } + + @Deprecated + public DeployedArtifact createDeployedArtifact() { + class DeployedArtifactImpl extends ArtifactImpl implements DeployedArtifact { + } + return new DeployedArtifactImpl(); + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java new file mode 100644 index 0000000000..3239bfd003 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.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.contribution.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * The representation of a deployed contribution + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +class ContributionImpl implements Contribution { + private String uri; + private String location; + private Object model; + private byte[] contents; + private boolean unresolved; + private List exports = new ArrayList(); + private List imports = new ArrayList(); + private List deployables = new ArrayList(); + private List artifacts = new ArrayList(); + private ModelResolver modelResolver; + + // FIXME remove this dependency on Java ClassLoaders + private ClassLoader classLoader; + + ContributionImpl() { + } + + public String getLocation() { + return this.location; + } + + public void setLocation(String location) { + this.location = location; + } + + //FIXME Remove dependency on Java ClassLoaders + public ClassLoader getClassLoader() { + return classLoader; + } + + //FIXME Remove dependency on Java ClassLoaders + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + + public String getURI() { + return this.uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public Object getModel() { + return model; + } + + public void setModel(Object model) { + this.model = model; + } + + public byte[] getContents() { + return contents; + } + + public void setContents(byte[] contents) { + this.contents = contents; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean unresolved) { + this.unresolved = unresolved; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + public List getExports() { + return exports; + } + + public List getImports() { + return imports; + } + + public List getDeployables() { + return deployables; + } + + public List getArtifacts() { + return artifacts; + } + + @Override + public int hashCode() { + return uri.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof Artifact) { + return uri.equals(((Artifact)obj).getURI()); + } else { + return false; + } + } + } + + @Override + public String toString() { + return "Contribution : " + uri + " \n" + + "from: " + location; + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java new file mode 100644 index 0000000000..f9116134fa --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.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.contribution.processor; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; + +/** + * Base interface for artifact processors. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface ArtifactProcessor { + + /** + * Resolve references from this model to other models. For example references + * from a composite to another one, or references from a composite to a WSDL + * model. + * + * @param model The model to resolve + * @param resolver The resolver to use to resolve referenced models + */ + void resolve(M model, ModelResolver resolver) throws ContributionResolveException; + + /** + * Returns the type of model handled by this artifact processor. + * + * @return The type of model handled by this artifact processor + */ + Class getModelType(); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..cf5956a8e7 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * An extension point for artifact processors. + * + * @version $Rev: 616133 $ $Date: 2008-01-28 17:45:50 -0800 (Mon, 28 Jan 2008) $ + */ +public interface ArtifactProcessorExtensionPoint

{ + + /** + * Add an artifact processor. + * + * @param artifactProcessor The artifact processor to add + */ + void addArtifactProcessor(P artifactProcessor); + + /** + * Remove an artifact processor. + * + * @param artifactProcessor The artifact processor to remove + */ + void removeArtifactProcessor(P artifactProcessor); + + /** + * Returns the processor associated with the given artifact type. + * + * @param artifactType An artifact type + * @return The processor associated with the given artifact type + */ + P getProcessor(Object artifactType); + + /** + * Returns the processor associated with the given model type. + * + * @param modelType A model type + * @return The processor associated with the given model type + */ + P getProcessor(Class modelType); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java new file mode 100644 index 0000000000..832a82a4f0 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java @@ -0,0 +1,512 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.processor; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringTokenizer; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + + +/** + * A base class with utility methods for the other artifact processors in this module. + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public abstract class BaseStAXArtifactProcessor { + + /** + * Returns a QName from a string. + * @param reader + * @param value + * @return + */ + protected QName getQNameValue(XMLStreamReader reader, String value) { + if (value != null) { + int index = value.indexOf(':'); + String prefix = index == -1 ? "" : value.substring(0, index); + String localName = index == -1 ? value : value.substring(index + 1); + String ns = reader.getNamespaceContext().getNamespaceURI(prefix); + if (ns == null) { + ns = ""; + } + return new QName(ns, localName, prefix); + } else { + return null; + } + } + + /** + * Returns the boolean value of an attribute. + * @param reader + * @param name + * @return + */ + protected boolean getBoolean(XMLStreamReader reader, String name) { + String value = reader.getAttributeValue(null, name); + if (value == null) { + return false; + } + return Boolean.valueOf(value); + } + + /** + * Returns the QName value of an attribute. + * @param reader + * @param name + * @return + */ + protected QName getQName(XMLStreamReader reader, String name) { + String qname = reader.getAttributeValue(null, name); + return getQNameValue(reader, qname); + } + + /** + * Returns the value of an attribute as a list of QNames. + * @param reader + * @param name + * @return + */ + protected List getQNames(XMLStreamReader reader, String name) { + String value = reader.getAttributeValue(null, name); + if (value != null) { + List qnames = new ArrayList(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + qnames.add(getQName(reader, tokens.nextToken())); + } + return qnames; + } else { + return Collections.emptyList(); + } + } + + /** + * Returns the string value of an attribute. + * @param reader + * @param name + * @return + */ + protected String getString(XMLStreamReader reader, String name) { + return reader.getAttributeValue(null, name); + } + + /** + * Test if an attribute is explicitly set + * @param reader + * @param name + * @return + */ + protected boolean isSet(XMLStreamReader reader, String name) { + return reader.getAttributeValue(null, name) != null; + } + + /** + * Returns the value of xsi:type attribute + * @param reader The XML stream reader + * @return The QName of the type, if the attribute is not present, null is + * returned. + */ + protected QName getXSIType(XMLStreamReader reader) { + String qname = reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type"); + return getQNameValue(reader, qname); + } + + /** + * Parse the next child element. + * @param reader + * @return + * @throws XMLStreamException + */ + protected boolean nextChildElement(XMLStreamReader reader) throws XMLStreamException { + while (reader.hasNext()) { + int event = reader.next(); + if (event == END_ELEMENT) { + return false; + } + if (event == START_ELEMENT) { + return true; + } + } + return false; + } + + /** + * Advance the stream to the next END_ELEMENT event skipping any nested + * content. + * @param reader the reader to advance + * @throws XMLStreamException if there was a problem reading the stream + */ + protected void skipToEndElement(XMLStreamReader reader) throws XMLStreamException { + int depth = 0; + while (reader.hasNext()) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + depth++; + } else if (event == XMLStreamConstants.END_ELEMENT) { + if (depth == 0) { + return; + } + depth--; + } + } + } + + /** + * + * @param writer + * @param uri + * @throws XMLStreamException + */ + private String writeElementPrefix(XMLStreamWriter writer, String uri) throws XMLStreamException { + if (uri == null) { + return null; + } + String prefix = writer.getPrefix(uri); + if (prefix != null) { + return null; + } else { + + // Find an available prefix and bind it to the given URI + NamespaceContext nsc = writer.getNamespaceContext(); + for (int i=1; ; i++) { + prefix = "ns" + i; + if (nsc.getNamespaceURI(prefix) == null) { + break; + } + } + writer.setPrefix(prefix, uri); + return prefix; + } + + } + + /** + * Start an element. + * @param uri + * @param name + * @param attrs + * @throws XMLStreamException + */ + protected void writeStart(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException { + String prefix = writeElementPrefix(writer, uri); + writeAttributePrefixes(writer, attrs); + writer.writeStartElement(uri, name); + + if (prefix != null){ + writer.writeNamespace(prefix,uri); + } + writeAttributes(writer, attrs); + } + + /** + * Start an element. + * @param qname + * @param attrs + * @throws XMLStreamException + */ + protected void writeStart(XMLStreamWriter writer, QName qname, XAttr... attrs) throws XMLStreamException { + writeStart(writer, qname.getNamespaceURI(), qname.getLocalPart(), attrs); + } + + /** + * End an element. + * @param writer + * @throws XMLStreamException + */ + protected void writeEnd(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * Start a document. + * @param writer + * @throws XMLStreamException + */ + protected void writeStartDocument(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException { + writer.writeStartDocument(); + writer.setDefaultNamespace(uri); + writeStart(writer, uri, name, attrs); + writer.writeDefaultNamespace(uri); + } + + /** + * Start a document. + * @param writer + * @param qname + * @param attrs + * @throws XMLStreamException + */ + protected void writeStartDocument(XMLStreamWriter writer, QName qname, XAttr... attrs) throws XMLStreamException { + writeStartDocument(writer, qname.getNamespaceURI(), qname.getLocalPart(), attrs); + } + + /** + * End a document. + * @param writer + * @throws XMLStreamException + */ + protected void writeEndDocument(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndDocument(); + } + + /** + * Write attributes to the current element. + * @param writer + * @param attrs + * @throws XMLStreamException + */ + protected void writeAttributes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException { + for (XAttr attr : attrs) { + if (attr != null) + attr.write(writer); + } + } + + /** + * Write attribute prefixes to the current element. + * @param writer + * @param attrs + * @throws XMLStreamException + */ + protected void writeAttributePrefixes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException { + for (XAttr attr : attrs) { + if (attr != null) + attr.writePrefix(writer); + } + } + + /** + * Represents an XML attribute that needs to be written to a document. + */ + public static class XAttr { + + private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0"; + + private String uri = SCA10_NS; + private String name; + private Object value; + + public XAttr(String uri, String name, String value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, String value) { + this(null, name, value); + } + + public XAttr(String uri, String name, List values) { + this.uri = uri; + this.name = name; + this.value = values; + } + + public XAttr(String name, List values) { + this(null, name, values); + } + + public XAttr(String uri, String name, Boolean value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, Boolean value) { + this(null, name, value); + } + + public XAttr(String uri, String name, QName value) { + this.uri = uri; + this.name = name; + this.value = value; + } + + public XAttr(String name, QName value) { + this(null, name, value); + } + + /** + * Writes a string from a QName and registers a prefix for its namespace. + * @param reader + * @param value + * @return + */ + private String writeQNameValue(XMLStreamWriter writer, QName qname) throws XMLStreamException { + if (qname != null) { + String prefix = qname.getPrefix(); + String uri = qname.getNamespaceURI(); + prefix = writer.getPrefix(uri); + if (prefix != null && prefix.length() > 0) { + + // Use the prefix already bound to the given URI + return prefix + ":" + qname.getLocalPart(); + } else { + + // Find an available prefix and bind it to the given URI + NamespaceContext nsc = writer.getNamespaceContext(); + for (int i=1; ; i++) { + prefix = "ns" + i; + if (nsc.getNamespaceURI(prefix) == null) { + break; + } + } + writer.setPrefix(prefix, uri); + writer.writeNamespace(prefix, uri); + return prefix + ":" + qname.getLocalPart(); + } + } else { + return null; + } + } + + /** + * Registers a prefix for the namespace of a QName. + * @param reader + * @param value + * @return + */ + private void writeQNamePrefix(XMLStreamWriter writer, QName qname) throws XMLStreamException { + if (qname != null) { + String prefix = qname.getPrefix(); + String uri = qname.getNamespaceURI(); + prefix = writer.getPrefix(uri); + if (prefix != null) { + return; + } else { + + // Find an available prefix and bind it to the given URI + NamespaceContext nsc = writer.getNamespaceContext(); + for (int i=1; ; i++) { + prefix = "ns" + i; + if (nsc.getNamespaceURI(prefix) == null) { + break; + } + } + writer.setPrefix(prefix, uri); + } + } + } + + /** + * Write to document + * @param writer + * @throws XMLStreamException + */ + public void write(XMLStreamWriter writer) throws XMLStreamException { + String str; + if (value instanceof QName) { + + // Write a QName + str = writeQNameValue(writer, (QName)value); + + } else if (value instanceof List) { + + // Write a list of values + List values = (List)value; + if (values.isEmpty()) { + return; + } + StringBuffer buffer = new StringBuffer(); + for (Object v: values) { + if (v == null) { + // Skip null values + continue; + } + + if (v instanceof XAttr) { + // Write an XAttr value + ((XAttr)v).write(writer); + continue; + } + + if (buffer.length() != 0) { + buffer.append(' '); + } + if (v instanceof QName) { + // Write a QName value + buffer.append(writeQNameValue(writer, (QName)v)); + } else { + // Write value as a string + buffer.append(String.valueOf(v)); + } + } + str = buffer.toString(); + + } else { + + // Write a string + if (value == null) { + return; + } + str = String.valueOf(value); + } + if (str.length() == 0) { + return; + } + + // Write the attribute + if (uri != null && !uri.equals(SCA10_NS)) { + writer.writeAttribute(uri, name, str); + } else { + writer.writeAttribute(name,str); + } + } + + /** + * Registers a prefix for the namespace of a QName or list of QNames + * @param writer + * @throws XMLStreamException + */ + public void writePrefix(XMLStreamWriter writer) throws XMLStreamException { + if (value instanceof QName) { + + // Write prefix for a single QName value + writeQNamePrefix(writer, (QName)value); + + } else if (value instanceof List) { + + // Write prefixes for a list of values + for (Object v: (List)value) { + if (v instanceof QName) { + // Write prefix for a QName value + writeQNamePrefix(writer, (QName)v); + + } else if (v instanceof XAttr) { + // Write prefix for an XAttr value + ((XAttr)v).writePrefix(writer); + } + } + } + } + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..68dcf8dbad --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.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.contribution.processor; + +import java.util.HashMap; +import java.util.Map; + +/** + * The default implementation of an artifact processor extension point. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +abstract class DefaultArtifactProcessorExtensionPoint

{ + protected final Map processorsByArtifactType = new HashMap(); + protected final Map, P> processorsByModelType = new HashMap, P>(); + + /** + * Constructs a new loader registry. + */ + DefaultArtifactProcessorExtensionPoint() { + } + + /** + * Returns the processor associated with the given artifact type. + * + * @param artifactType An artifact type + * @return The processor associated with the given artifact type + */ + public P getProcessor(Object artifactType) { + return processorsByArtifactType.get(artifactType); + } + + /** + * Returns the processor associated with the given model type. + * + * @param modelType A model type + * @return The processor associated with the given model type + */ + public P getProcessor(Class modelType) { + Class[] classes = modelType.getInterfaces(); + for (Class c : classes) { + P processor = processorsByModelType.get(c); + if (processor != null) { + return processor; + } + } + return processorsByModelType.get(modelType); + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java new file mode 100644 index 0000000000..2a98478109 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.service.ContributionException; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Default implementation of a package processor extension point. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultPackageProcessorExtensionPoint implements PackageProcessorExtensionPoint { + + private Map processors = new HashMap(); + private boolean loaded; + + public DefaultPackageProcessorExtensionPoint() { + } + + public void addPackageProcessor(PackageProcessor processor) { + processors.put(processor.getPackageType(), processor); + } + + public void removePackageProcessor(PackageProcessor processor) { + processors.remove(processor.getPackageType()); + } + + public PackageProcessor getPackageProcessor(String contentType) { + loadProcessors(); + return processors.get(contentType); + } + + private void loadProcessors() { + if (loaded) + return; + + // Get the processor service declarations + Set processorDeclarations; + try { + processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(PackageProcessor.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + for (ServiceDeclaration processorDeclaration: processorDeclarations) { + Map attributes = processorDeclaration.getAttributes(); + + // Load a URL artifact processor + String packageType = attributes.get("type"); + + // Create a processor wrapper and register it + PackageProcessor processor = new LazyPackageProcessor(packageType, processorDeclaration); + addPackageProcessor(processor); + } + + loaded = true; + } + + /** + * A facade for package processors. + */ + private static class LazyPackageProcessor implements PackageProcessor { + + private ServiceDeclaration processorDeclaration; + private String packageType; + private PackageProcessor processor; + + private LazyPackageProcessor(String packageType, ServiceDeclaration processorDeclaration) { + this.processorDeclaration = processorDeclaration; + this.packageType = packageType; + } + + public URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException { + return getProcessor().getArtifactURL(packageSourceURL, artifact); + } + + public List getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException { + return getProcessor().getArtifacts(packageSourceURL, inputStream); + } + + public String getPackageType() { + return packageType; + } + + @SuppressWarnings("unchecked") + private PackageProcessor getProcessor() { + if (processor == null) { + try { + Class processorClass = (Class)processorDeclaration.loadClass(); + Constructor constructor = processorClass.getConstructor(); + processor = constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return processor; + } + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..f9c21947f7 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.Map; +import java.util.Set; + +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.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * The default implementation of an extension point for StAX artifact processors. + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public class DefaultStAXArtifactProcessorExtensionPoint extends + DefaultArtifactProcessorExtensionPoint implements StAXArtifactProcessorExtensionPoint { + + private ModelFactoryExtensionPoint modelFactories; + private boolean loaded; + + /** + * Constructs a new extension point. + */ + public DefaultStAXArtifactProcessorExtensionPoint(ModelFactoryExtensionPoint modelFactories) { + this.modelFactories = modelFactories; + } + + public void addArtifactProcessor(StAXArtifactProcessor artifactProcessor) { + processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor); + processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor); + } + + public void removeArtifactProcessor(StAXArtifactProcessor artifactProcessor) { + processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType()); + processorsByModelType.remove(artifactProcessor.getModelType()); + } + + @Override + public StAXArtifactProcessor getProcessor(Class modelType) { + loadArtifactProcessors(); + return super.getProcessor(modelType); + } + + @Override + public StAXArtifactProcessor getProcessor(Object artifactType) { + loadArtifactProcessors(); + return super.getProcessor(artifactType); + } + + /** + * Returns a QName object from a QName expressed as {ns}name + * or ns#name. + * + * @param qname + * @return + */ + private static QName getQName(String qname) { + if (qname == null) { + return null; + } + qname = qname.trim(); + if (qname.startsWith("{")) { + int h = qname.indexOf('}'); + if (h != -1) { + return new QName(qname.substring(1, h), qname.substring(h + 1)); + } + } else { + int h = qname.indexOf('#'); + if (h != -1) { + return new QName(qname.substring(0, h), qname.substring(h + 1)); + } + } + throw new IllegalArgumentException("Invalid qname: "+qname); + } + + /** + * Lazily load artifact processors registered in the extension point. + */ + private void loadArtifactProcessors() { + if (loaded) + return; + + // Get the processor service declarations + Set processorDeclarations; + try { + processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(StAXArtifactProcessor.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + for (ServiceDeclaration processorDeclaration : processorDeclarations) { + Map attributes = processorDeclaration.getAttributes(); + + // Load a StAX artifact processor + + // Get the model QName + QName artifactType = getQName(attributes.get("qname")); + + // Get the model class name + String modelTypeName = attributes.get("model"); + + // Get the model factory class name + String factoryName = attributes.get("factory"); + + // Create a processor wrapper and register it + StAXArtifactProcessor processor = + new LazyStAXArtifactProcessor(modelFactories, artifactType, modelTypeName, factoryName, + processorDeclaration); + addArtifactProcessor(processor); + } + + loaded = true; + } + + /** + * A wrapper around an Artifact processor class allowing lazy loading and + * initialization of artifact processors. + */ + private static class LazyStAXArtifactProcessor implements StAXArtifactProcessor { + + private ModelFactoryExtensionPoint modelFactories; + private QName artifactType; + private String modelTypeName; + private String factoryName; + private ServiceDeclaration processorDeclaration; + private StAXArtifactProcessor processor; + private Class modelType; + + LazyStAXArtifactProcessor(ModelFactoryExtensionPoint modelFactories, + QName artifactType, + String modelTypeName, + String factoryName, + ServiceDeclaration processorDeclaration) { + + this.modelFactories = modelFactories; + this.artifactType = artifactType; + this.modelTypeName = modelTypeName; + this.factoryName = factoryName; + this.processorDeclaration = processorDeclaration; + } + + public QName getArtifactType() { + return artifactType; + } + + @SuppressWarnings("unchecked") + private StAXArtifactProcessor getProcessor() { + if (processor == null) { + + if (processorDeclaration.getClassName() + .equals("org.apache.tuscany.sca.assembly.xml.DefaultBeanModelProcessor")) { + + // Specific initialization for the DefaultBeanModelProcessor + AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + PolicyFactory policyFactory = modelFactories.getFactory(PolicyFactory.class); + try { + Class processorClass = + (Class)processorDeclaration.loadClass(); + Object modelFactory; + if (factoryName != null) { + Class factoryClass = (Class)processorDeclaration.loadClass(factoryName); + modelFactory = modelFactories.getFactory(factoryClass); + } else { + modelFactory = null; + } + Constructor constructor = + processorClass.getConstructor(AssemblyFactory.class, + PolicyFactory.class, + QName.class, + Class.class, + Object.class); + processor = + constructor.newInstance(assemblyFactory, + policyFactory, + artifactType, + getModelType(), + modelFactory); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } else { + + // Load and instantiate the processor class + try { + Class processorClass = + (Class)processorDeclaration.loadClass(); + Constructor constructor = + processorClass.getConstructor(ModelFactoryExtensionPoint.class); + processor = constructor.newInstance(modelFactories); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + return processor; + } + + public Object read(XMLStreamReader inputSource) throws ContributionReadException, XMLStreamException { + return getProcessor().read(inputSource); + } + + @SuppressWarnings("unchecked") + public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException, + XMLStreamException { + getProcessor().write(model, outputSource); + } + + public Class getModelType() { + if (modelType == null) { + try { + modelType = processorDeclaration.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException { + getProcessor().resolve(model, resolver); + } + + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..574ffc5f04 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.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.contribution.processor; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.net.URL; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * The default implementation of a URL artifact processor extension point. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultURLArtifactProcessorExtensionPoint + extends DefaultArtifactProcessorExtensionPoint + implements URLArtifactProcessorExtensionPoint { + + private ModelFactoryExtensionPoint modelFactories; + private boolean loaded; + + /** + * Constructs a new extension point. + */ + public DefaultURLArtifactProcessorExtensionPoint(ModelFactoryExtensionPoint modelFactories) { + this.modelFactories = modelFactories; + } + + public void addArtifactProcessor(URLArtifactProcessor artifactProcessor) { + processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor); + processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor); + } + + public void removeArtifactProcessor(URLArtifactProcessor artifactProcessor) { + processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType()); + processorsByModelType.remove(artifactProcessor.getModelType()); + } + + @Override + public URLArtifactProcessor getProcessor(Class modelType) { + loadProcessors(); + return super.getProcessor(modelType); + } + + @Override + public URLArtifactProcessor getProcessor(Object artifactType) { + loadProcessors(); + return super.getProcessor(artifactType); + } + + /** + * Lazily load artifact processors registered in the extension point. + */ + private void loadProcessors() { + if (loaded) + return; + + // Get the processor service declarations + Set processorDeclarations; + try { + processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(URLArtifactProcessor.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + for (ServiceDeclaration processorDeclaration: processorDeclarations) { + Map attributes = processorDeclaration.getAttributes(); + // Load a URL artifact processor + String artifactType = attributes.get("type"); + String modelTypeName = attributes.get("model"); + + // Create a processor wrapper and register it + URLArtifactProcessor processor = new LazyURLArtifactProcessor(modelFactories, artifactType, modelTypeName, processorDeclaration); + addArtifactProcessor(processor); + } + + loaded = true; + } + + /** + * A wrapper around an Artifact processor class allowing lazy loading and + * initialization of artifact processors. + */ + private static class LazyURLArtifactProcessor implements URLArtifactProcessor { + + private ModelFactoryExtensionPoint modelFactories; + private String artifactType; + private String modelTypeName; + private ServiceDeclaration processorDeclaration; + private URLArtifactProcessor processor; + private Class modelType; + + LazyURLArtifactProcessor(ModelFactoryExtensionPoint modelFactories, + String artifactType, + String modelTypeName, + ServiceDeclaration processorDeclaration) { + this.modelFactories = modelFactories; + this.artifactType = artifactType; + this.modelTypeName = modelTypeName; + this.processorDeclaration = processorDeclaration; + } + + public String getArtifactType() { + return artifactType; + } + + @SuppressWarnings("unchecked") + private URLArtifactProcessor getProcessor() { + if (processor == null) { + try { + Class processorClass = (Class)processorDeclaration.loadClass(); + Constructor constructor = processorClass.getConstructor(ModelFactoryExtensionPoint.class); + processor = constructor.newInstance(modelFactories); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return processor; + } + + public Object read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException { + return getProcessor().read(contributionURL, artifactURI, artifactURL); + } + + public Class getModelType() { + if (modelType == null) { + try { + modelType = processorDeclaration.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException { + getProcessor().resolve(model, resolver); + } + + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java new file mode 100644 index 0000000000..dcb2c05186 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.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.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.net.URLConnection; +import java.util.List; + +import javax.xml.XMLConstants; +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +/** + * Default implementation of an XMLInputFactory that creates validating + * XMLStreamReaders. + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +public class DefaultValidatingXMLInputFactory extends XMLInputFactory { + + private XMLInputFactory inputFactory; + private ValidationSchemaExtensionPoint schemas; + private boolean initialized; + private Schema aggregatedSchema; + + /** + * Constructs a new XMLInputFactory. + * + * @param inputFactory + * @param schemas + */ + public DefaultValidatingXMLInputFactory(XMLInputFactory inputFactory, ValidationSchemaExtensionPoint schemas) { + this.inputFactory = inputFactory; + this.schemas = schemas; + } + + /** + * Initialize the registered schemas and create an aggregated schema for + * validation. + */ + private void initializeSchemas() { + if (initialized) { + return; + } + initialized = true; + + // Load the XSDs registered in the validation schema extension point + try { + List uris = schemas.getSchemas(); + int n = uris.size(); + final Source[] sources = new Source[n]; + for (int i =0; i < n; i++) { + final String uri = uris.get(i); + // Allow privileged access to open URL stream. Requires FilePermission in security policy. + final URL url = new URL( uri ); + InputStream urlStream; + try { + urlStream = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public InputStream run() throws IOException { + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + return connection.getInputStream(); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException)e.getException(); + } + sources[i] = new StreamSource(urlStream, uri); + } + + // Create an aggregated validation schemas from all the XSDs + final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + // Allow privileged access to check files. Requires FilePermission + // in security policy. + try { + aggregatedSchema = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Schema run() throws SAXException { + return schemaFactory.newSchema(sources); + } + }); + } catch (PrivilegedActionException e) { + throw (SAXException)e.getException(); + } + + } catch (Error e) { + // FIXME Log this, some old JDKs don't support XMLSchema validation + //e.printStackTrace(); + } catch (SAXParseException e) { + throw new IllegalStateException(e); + } catch (Exception e) { + //FIXME Log this, some old JDKs don't support XMLSchema validation + e.printStackTrace(); + } + } + + public XMLEventReader createFilteredReader(XMLEventReader arg0, EventFilter arg1) throws XMLStreamException { + return inputFactory.createFilteredReader(arg0, arg1); + } + + public XMLStreamReader createFilteredReader(XMLStreamReader arg0, StreamFilter arg1) throws XMLStreamException { + return inputFactory.createFilteredReader(arg0, arg1); + } + + public XMLEventReader createXMLEventReader(InputStream arg0, String arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + public XMLEventReader createXMLEventReader(InputStream arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + public XMLEventReader createXMLEventReader(Reader arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + public XMLEventReader createXMLEventReader(Source arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + public XMLEventReader createXMLEventReader(String arg0, InputStream arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + public XMLEventReader createXMLEventReader(String arg0, Reader arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + public XMLEventReader createXMLEventReader(XMLStreamReader arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + public XMLStreamReader createXMLStreamReader(InputStream arg0, String arg1) throws XMLStreamException { + initializeSchemas(); + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema); + } + + public XMLStreamReader createXMLStreamReader(InputStream arg0) throws XMLStreamException { + initializeSchemas(); + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema); + } + + public XMLStreamReader createXMLStreamReader(Reader arg0) throws XMLStreamException { + initializeSchemas(); + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema); + } + + public XMLStreamReader createXMLStreamReader(Source arg0) throws XMLStreamException { + initializeSchemas(); + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema); + } + + public XMLStreamReader createXMLStreamReader(String arg0, InputStream arg1) throws XMLStreamException { + initializeSchemas(); + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema); + } + + public XMLStreamReader createXMLStreamReader(String arg0, Reader arg1) throws XMLStreamException { + initializeSchemas(); + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema); + } + + public XMLEventAllocator getEventAllocator() { + return inputFactory.getEventAllocator(); + } + + public Object getProperty(String arg0) throws IllegalArgumentException { + return inputFactory.getProperty(arg0); + } + + public XMLReporter getXMLReporter() { + return inputFactory.getXMLReporter(); + } + + public XMLResolver getXMLResolver() { + return inputFactory.getXMLResolver(); + } + + public boolean isPropertySupported(String arg0) { + return inputFactory.isPropertySupported(arg0); + } + + public void setEventAllocator(XMLEventAllocator arg0) { + inputFactory.setEventAllocator(arg0); + } + + public void setProperty(String arg0, Object arg1) throws IllegalArgumentException { + inputFactory.setProperty(arg0, arg1); + } + + public void setXMLReporter(XMLReporter arg0) { + inputFactory.setXMLReporter(arg0); + } + + public void setXMLResolver(XMLResolver arg0) { + inputFactory.setXMLResolver(arg0); + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java new file mode 100644 index 0000000000..e27add9b81 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Default implementation of an extension point for XML schemas. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultValidationSchemaExtensionPoint implements ValidationSchemaExtensionPoint { + + private List schemas = new ArrayList(); + private boolean loaded; + + public void addSchema(String uri) { + schemas.add(uri); + } + + public void removeSchema(String uri) { + schemas.remove(uri); + } + + /** + * Load schema declarations from META-INF/services/ + * org.apache.tuscany.sca.contribution.processor.ValidationSchema files + */ + private void loadSchemas() { + if (loaded) + return; + + // Get the schema declarations + Set schemaDeclarations; + try { + schemaDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations("org.apache.tuscany.sca.contribution.processor.ValidationSchema"); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Find each schema + for (ServiceDeclaration schemaDeclaration: schemaDeclarations) { + URL url = schemaDeclaration.getResource(); + if (url == null) { + throw new IllegalArgumentException(new FileNotFoundException(schemaDeclaration.getClassName())); + } + schemas.add(url.toString()); + } + + loaded = true; + } + + public List getSchemas() { + loadSchemas(); + return schemas; + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java new file mode 100644 index 0000000000..0b1587d10a --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.contribution.service.ContributionException; +import org.apache.tuscany.sca.contribution.service.TypeDescriber; +import org.apache.tuscany.sca.contribution.service.UnsupportedPackageTypeException; + +/** + * Implementation of an extensible package processor. + * + * Takes a package processor extension point and delegates to the proper package + * processor from the extension point based on the package's content type. + * + * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $ + */ +public class ExtensiblePackageProcessor implements PackageProcessor { + + private PackageProcessorExtensionPoint processors; + private TypeDescriber packageTypeDescriber; + + public ExtensiblePackageProcessor(PackageProcessorExtensionPoint processors, TypeDescriber packageTypeDescriber) { + this.processors = processors; + this.packageTypeDescriber = packageTypeDescriber; + } + + public List getArtifacts(URL packageSourceURL, InputStream inputStream) + throws ContributionException, IOException { + String packageType = this.packageTypeDescriber.getType(packageSourceURL, null); + if (packageType == null) { + throw new UnsupportedPackageTypeException("Unsupported contribution package type: " + packageSourceURL.toString()); + } + + PackageProcessor packageProcessor = this.processors.getPackageProcessor(packageType); + if (packageProcessor == null) { + throw new UnsupportedPackageTypeException("Unsupported contribution package type: " + packageType); + } + + return packageProcessor.getArtifacts(packageSourceURL, inputStream); + } + + public URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException { + String contentType = this.packageTypeDescriber.getType(packageSourceURL, null); + PackageProcessor packageProcessor = this.processors.getPackageProcessor(contentType); + return packageProcessor.getArtifactURL(packageSourceURL, artifact); + } + + public String getPackageType() { + return null; + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java new file mode 100644 index 0000000000..ea2bfdd3ac --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +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.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.contribution.service.UnrecognizedElementException; + +/** + * Implementation of an extensible StAX artifact processor. + * + * Takes a StAXArtifactProcessorExtensionPoint and delegates to the proper + * StAXArtifactProcessor by element QName + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public class ExtensibleStAXArtifactProcessor + implements StAXArtifactProcessor { + + private static final Logger logger = Logger.getLogger(ExtensibleStAXArtifactProcessor.class.getName()); + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessorExtensionPoint processors; + + /** + * Constructs a new ExtensibleStAXArtifactProcessor. + * @param processors + * @param inputFactory + * @param outputFactory + */ + public ExtensibleStAXArtifactProcessor(StAXArtifactProcessorExtensionPoint processors, XMLInputFactory inputFactory, XMLOutputFactory outputFactory) { + super(); + this.processors = processors; + this.inputFactory = inputFactory; + this.outputFactory = outputFactory; + //this.outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE); + } + + public Object read(XMLStreamReader source) throws ContributionReadException, XMLStreamException { + + // Delegate to the processor associated with the element QName + QName name = source.getName(); + StAXArtifactProcessor processor = (StAXArtifactProcessor)processors.getProcessor(name); + if (processor == null) { + if (logger.isLoggable(Level.WARNING)) { + Location location = source.getLocation(); + logger.warning("Element " + name + " cannot be processed. (" + location + ")"); + } + return null; + } + return processor.read(source); + } + + @SuppressWarnings("unchecked") + public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException, XMLStreamException { + + // Delegate to the processor associated with the model type + if (model != null) { + StAXArtifactProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.write(model, outputSource); + } else { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("No StAX processor is configured to handle " + model.getClass()); + } + } + } + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException { + + // Delegate to the processor associated with the model type + if (model != null) { + StAXArtifactProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.resolve(model, resolver); + } + } + } + + /** + * Read a model from an InputStream. + * @param is The artifact InputStream + * @param type Model type + * @return The model + * @throws ContributionReadException + */ + public M read(InputStream is, Class type) throws ContributionReadException { + try { + XMLStreamReader reader; + try { + reader = inputFactory.createXMLStreamReader(is); + try { + reader.nextTag(); + QName name = reader.getName(); + Object mo = read(reader); + if (type.isInstance(mo)) { + return type.cast(mo); + } else { + UnrecognizedElementException e = new UnrecognizedElementException(name); + throw e; + } + } catch (ContributionReadException e) { + Location location = reader.getLocation(); + e.setLine(location.getLineNumber()); + e.setColumn(location.getColumnNumber()); + throw e; + } finally { + try { + reader.close(); + } catch (XMLStreamException e) { + // ignore + } + } + } finally { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } catch (XMLStreamException e) { + ContributionReadException ce = new ContributionReadException(e); + throw ce; + } + } + + /** + * Write a model to an OutputStream. + * @param model + * @param os + * @throws ContributionWriteException + */ + public void write(Object model, OutputStream os) throws ContributionWriteException { + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(os); + write(model, writer); + writer.flush(); + writer.close(); + } catch (XMLStreamException e) { + throw new ContributionWriteException(e); + } + } + + public QName getArtifactType() { + return null; + } + + public Class getModelType() { + return null; + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java new file mode 100644 index 0000000000..c399800459 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +import java.net.URI; +import java.net.URL; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.UnrecognizedElementException; + +/** + * Implementation of an extensible URL artifact processor. + * + * Takes a URLArtifactProcessorExtensionPoint and delegates to the proper URLArtifactProcessor + * by either fileName or fileExtention + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public class ExtensibleURLArtifactProcessor + implements URLArtifactProcessor { + + private URLArtifactProcessorExtensionPoint processors; + + /** + * Constructs a new ExtensibleURLArtifactProcessor. + * + * @param processors + */ + public ExtensibleURLArtifactProcessor(URLArtifactProcessorExtensionPoint processors) { + this.processors = processors; + } + + @SuppressWarnings("unchecked") + public Object read(URL contributionURL, URI sourceURI, URL sourceURL) throws ContributionReadException { + URLArtifactProcessor processor = null; + + // Delegate to the processor associated with file extension + String fileName = getFileName(sourceURL); + + //try to retrieve a processor for the specific filename + processor = (URLArtifactProcessor)processors.getProcessor(fileName); + + if (processor == null) { + //try to find my file type (extension) + String extension = sourceURL.getPath(); + + int extensionStart = extension.lastIndexOf('.'); + //handle files without extension (e.g NOTICE) + if (extensionStart > 0) { + extension = extension.substring(extensionStart); + processor = (URLArtifactProcessor)processors.getProcessor(extension); + } + } + + if (processor == null) { + return null; + } + return processor.read(contributionURL, sourceURI, sourceURL); + } + + @SuppressWarnings("unchecked") + public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException { + + // Delegate to the processor associated with the model type + if (model != null) { + URLArtifactProcessor processor = processors.getProcessor(model.getClass()); + if (processor != null) { + processor.resolve(model, resolver); + } + } + } + + public M read(URL contributionURL, URI artifactURI, URL artifactUrl, Class type) + throws ContributionReadException { + Object mo = read(contributionURL, artifactURI, artifactUrl); + if (type.isInstance(mo)) { + return type.cast(mo); + } else { + UnrecognizedElementException e = new UnrecognizedElementException(null); + e.setResourceURI(artifactURI.toString()); + throw e; + } + } + + public String getArtifactType() { + return null; + } + + public Class getModelType() { + return null; + } + + /** + * Returns the file name from a URL. + * @param url + * @return + */ + private static String getFileName(URL url){ + String fileName = url.getPath(); + int pos = fileName.lastIndexOf("/"); + + return fileName.substring(pos +1); + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java new file mode 100644 index 0000000000..e4034c358e --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.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.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.contribution.service.ContributionException; + +/** + * Interface for contribution package processors + * + * Package processors understand the format of the contribution and how to get the + * artifacts in the contribution. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface PackageProcessor { + + /** + * Returns the type of package supported by this package processor. + * + * @return the package type + */ + String getPackageType(); + + /** + * Returns a list of artifacts in the contribution. + * + * @param packageSourceURL Contribution package location URL + * @param inputStream Optional content of the package + * @return List of artifact URIs + * @throws ContributionException + * @throws IOException + */ + List getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException; + + /** + * Return the URL for an artifact in the package. + * + * This is needed for archives such as jar files that have specific URL schemes + * for the artifacts they contain. + * + * @param packageSourceURL Contribution package location URL + * @param artifact The relative URI for the artifact + * @return The artifact URL + */ + URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException; + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java new file mode 100644 index 0000000000..97fd5fee76 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.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.contribution.processor; + +/** + * An extension point for package processors + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface PackageProcessorExtensionPoint { + + /** + * Register a PackageProcessor using the package type as the key. + * + * @param processor The package processor + */ + void addPackageProcessor(PackageProcessor processor); + + /** + * Unregister a PackageProcessor. + * + * @param processor The package processor + */ + void removePackageProcessor(PackageProcessor processor); + + /** + * Returns the PackageProcessor for the given package type. + * + * @param packageType The package type + * @return The package processor + */ + PackageProcessor getPackageProcessor(String packageType); + +} \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java new file mode 100644 index 0000000000..62e6bd0f86 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.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.contribution.processor; + +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.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; + +/** + * An artifact processor that can read models from a StAX XMLStreamReader. + * + * @version $Rev: 572267 $ $Date: 2007-09-03 02:46:41 -0700 (Mon, 03 Sep 2007) $ + */ +public interface StAXArtifactProcessor extends ArtifactProcessor { + + /** + * Reads a model from an XMLStreamReader. + * + * @param reader The XMLStreamReader + * @return A model representation of the input. + */ + M read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException; + + /** + * Writes a model to an XMLStreamWriter. + * + * @param model A model representing the source + * @param writer The XML stream writer + * @throws ContributionWriteException + * @throws XMLStreamException + */ + void write(M model, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException; + + /** + * Returns the type of artifact handled by this artifact processor. + * + * @return The type of artifact handled by this artifact processor + */ + QName getArtifactType(); +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..0bf0f81b5e --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * An extension point for StAX artifact processors. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface StAXArtifactProcessorExtensionPoint extends + ArtifactProcessorExtensionPoint { + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java new file mode 100644 index 0000000000..07e71aba5a --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.net.URI; +import java.net.URL; + +import org.apache.tuscany.sca.contribution.service.ContributionReadException; + +/** + * An artifact processor that can read models from a URL. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface URLArtifactProcessor extends ArtifactProcessor { + + /** + * Reads a model from a URL. + * + * @param contributionURL Contribution location URL + * @param artifactURI Artifact URI + * @param artifactURL Artifact location URL + * @return A model representation of the input. + */ + M read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException; + + /** + * Returns the type of artifact handled by this artifact processor. + * + * @return The type of artifact handled by this artifact processor + */ + String getArtifactType(); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java new file mode 100644 index 0000000000..653b0ed637 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.processor; + +/** + * An extension point for URL artifact processors. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface URLArtifactProcessorExtensionPoint extends + ArtifactProcessorExtensionPoint { + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java new file mode 100644 index 0000000000..8d5e2f33db --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java @@ -0,0 +1,336 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.processor; + +import java.util.logging.Logger; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.StreamReaderDelegate; +import javax.xml.validation.Schema; +import javax.xml.validation.ValidatorHandler; + +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * + * A validating XMLStreamReader that reports XMLSchema validation errors. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +class ValidatingXMLStreamReader extends StreamReaderDelegate implements XMLStreamReader { + private static final Logger logger = Logger.getLogger(ValidatingXMLStreamReader.class.getName()); + + private int level; + private ValidatorHandler handler; + + /** + * Constructs a new ValidatingXMLStreamReader. + * + * @param reader + * @param schema + * @throws XMLStreamException + */ + ValidatingXMLStreamReader(XMLStreamReader reader, Schema schema) throws XMLStreamException { + super(reader); + if (schema == null) { + return; + } + + handler = schema.newValidatorHandler(); + handler.setDocumentLocator(new LocatorAdapter()); + try { + handler.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + } catch (SAXException e) { + throw new XMLStreamException(e); + } + + // These validation errors are just warnings for us as we want to support + // running from an XML document with XSD validation errors, as long as we can + // get the metadata we need from the document + handler.setErrorHandler(new ErrorHandler() { + private String getMessage(SAXParseException e) { + return "XMLSchema validation problem in: " + e.getSystemId() + ", line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + "\n" + e.getMessage(); + } + + public void error(SAXParseException exception) throws SAXException { + logger.warning(getMessage(exception)); + } + + public void fatalError(SAXParseException exception) throws SAXException { + logger.warning(getMessage(exception)); + } + + public void warning(SAXParseException exception) throws SAXException { + logger.warning(getMessage(exception)); + } + }); + } + + @Override + public int next() throws XMLStreamException { + if (handler == null) { + return super.next(); + } + + int event = super.next(); + try { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(super.getPITarget(), super.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + case XMLStreamConstants.CDATA: + case XMLStreamConstants.SPACE: + case XMLStreamConstants.ENTITY_REFERENCE: + handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(); + level--; + break; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + break; + } + } catch (SAXException e) { + throw new XMLStreamException(e.getMessage(), e); + } + return event; + } + + @Override + public int nextTag() throws XMLStreamException { + if (handler == null) { + return super.nextTag(); + } + + for (;;) { + int event = super.getEventType(); + try { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(); + return event; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(super.getPITarget(), super.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + case XMLStreamConstants.CDATA: + case XMLStreamConstants.SPACE: + case XMLStreamConstants.ENTITY_REFERENCE: + handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(); + level--; + return event; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + return event; + } + } catch (SAXException e) { + throw new XMLStreamException(e); + } + super.next(); + } + } + + @Override + public String getElementText() throws XMLStreamException { + if (handler == null) { + return super.getElementText(); + } + + if (getEventType() != XMLStreamConstants.START_ELEMENT) { + return super.getElementText(); + } + StringBuffer text = new StringBuffer(); + + for (;;) { + int event = next(); + switch (event) { + case XMLStreamConstants.END_ELEMENT: + return text.toString(); + + case XMLStreamConstants.COMMENT: + case XMLStreamConstants.PROCESSING_INSTRUCTION: + continue; + + case CHARACTERS: + case CDATA: + case SPACE: + case ENTITY_REFERENCE: + text.append(getText()); + break; + + default: + break; + } + } + } + + /** + * Handle a start element event. + * + * @throws SAXException + */ + private void handleStartElement() throws SAXException { + + // send startPrefixMapping events immediately before startElement event + int nsCount = super.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = super.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, super.getNamespaceURI(i)); + } + + // fire startElement + QName qname = super.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + /** + * Handle an endElement event. + * + * @throws SAXException + */ + private void handleEndElement() throws SAXException { + + // fire endElement + QName qname = super.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not + // actually required by SAX + int nsCount = super.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = super.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes() { + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations + for (int i = 0; i < super.getNamespaceCount(); i++) { + String prefix = super.getNamespacePrefix(i); + String uri = super.getNamespaceURI(i); + if (prefix == null) { + attrs.addAttribute("", "", "xmlns", "CDATA", uri); + } else { + attrs.addAttribute("", "", "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < super.getAttributeCount(); i++) { + String uri = super.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = super.getAttributeLocalName(i); + String prefix = super.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = super.getAttributeType(i); + String value = super.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adapter for mapping Locator information. + */ + private final class LocatorAdapter implements Locator { + + private LocatorAdapter() { + } + + public int getColumnNumber() { + Location location = getLocation(); + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + Location location = getLocation(); + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + Location location = getLocation(); + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + Location location = getLocation(); + return location == null ? "" : location.getSystemId(); + } + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java new file mode 100644 index 0000000000..8316786ce0 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.processor; + +import java.util.List; + + +/** + * An extension point for XML schemas used for validation. + * + * @version $Rev: 581132 $ $Date: 2007-10-01 21:05:32 -0700 (Mon, 01 Oct 2007) $ + */ +public interface ValidationSchemaExtensionPoint { + + /** + * Add a schema. + * + * @param uri the URI of the schema + */ + void addSchema(String uri); + + /** + * Remove a schema. + * + * @param uri the URI of the schema + */ + void removeSchema(String uri); + + /** + * Returns the list of schemas registered in the extension point. + * @return the list of schemas + */ + List getSchemas(); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java new file mode 100644 index 0000000000..235e542e52 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.lang.ref.WeakReference; + +/** + * A weak reference to a class, which should be used to register classes + * with an ArtifactResolver and resolve these classes later. + * + * FIXME The core contribution model should not have dependencies on classes + * and ClassLoaders. This should move to the Java import support module. + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public class ClassReference { + + private WeakReference clazz; + private String className; + + /** + * Constructs a new ClassReference. + * + * @param clazz The class reference + */ + public ClassReference(Class clazz) { + this.clazz = new WeakReference(clazz); + this.className = clazz.getName(); + } + + /** + * Constructs a new ClassReference. + * + * @param className The class name + */ + public ClassReference(String className) { + this.className = className; + } + + /** + * Get the referenced class. + * + * @return The referenced class + */ + public Class getJavaClass() { + if (clazz != null) { + return clazz.get(); + } else { + return null; + } + } + + /** + * Get the referenced class name. + * + * @return The class name + */ + public String getClassName() { + return className; + } + + /** + * Returns true if the class reference is unresolved. + * + * @return Whether or not the class has been resolved + */ + public boolean isUnresolved() { + return clazz == null; + } + + @Override + public int hashCode() { + return className.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof ClassReference) { + return className.equals(((ClassReference)obj).className); + } else { + return false; + } + } + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java new file mode 100644 index 0000000000..e8a9edb275 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.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.contribution.resolver; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Export; +import org.apache.tuscany.sca.contribution.Import; + +/** + * A model resolver implementation that considers Exports in any available contribution + * + * @version $Rev: 560435 $ $Date: 2007-07-27 18:26:55 -0700 (Fri, 27 Jul 2007) $ + */ +public class DefaultImportAllModelResolver implements ModelResolver { + + private Import import_; + private List contributions; + + public DefaultImportAllModelResolver(Import import_, List contributions) { + this.import_ = import_; + this.contributions = contributions; + } + + public void addModel(Object resolved) { + throw new IllegalStateException(); + } + + public Object removeModel(Object resolved) { + throw new IllegalStateException(); + } + + public T resolveModel(Class modelClass, T unresolved) { + + //TODO optimize and cache results of the resolution later + + // Go over all available contributions + for (Contribution contribution : contributions) { + + // Go over all exports in the contribution + for (Export export : contribution.getExports()) { + + // If the export matches the export, try to resolve the model object + if (import_.match(export)) { + Object resolved = export.getModelResolver().resolveModel(modelClass, unresolved); + + // Return the resolved model object + if (resolved instanceof Base) { + if (!((Base)resolved).isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + } + } + + // Model object was not resolved + return unresolved; + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java new file mode 100644 index 0000000000..e8e635ad07 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.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.contribution.resolver; + +import java.util.HashMap; +import java.util.Map; + + +/** + * A default implementation of a model resolver based on a map. + * + * @version $Rev: 631277 $ $Date: 2008-02-26 08:23:26 -0800 (Tue, 26 Feb 2008) $ + */ +public class DefaultModelResolver implements ModelResolver { + + private Map map = new HashMap(); + + public DefaultModelResolver() { + } + + public T resolveModel(Class modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved) { + return map.remove(resolved); + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java new file mode 100644 index 0000000000..471cfde136 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.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.contribution.resolver; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + + +/** + * The default implementation of a model resolver extension point. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultModelResolverExtensionPoint implements ModelResolverExtensionPoint { + + private final Map, Class> resolvers = new HashMap, Class>(); + private Map loadedResolvers; + + /** + * Constructs a new DefaultModelResolverExtensionPoint. + */ + public DefaultModelResolverExtensionPoint() { + } + + public void addResolver(Class modelType, Class resolver) { + resolvers.put(modelType, resolver); + } + + public void removeResolver(Class modelType) { + resolvers.remove(modelType); + } + + @SuppressWarnings("unchecked") + public Class getResolver(Class modelType) { + loadModelResolvers(); + + Class[] classes = modelType.getInterfaces(); + for (Class c : classes) { + Class resolver = resolvers.get(c); + if (resolver == null) { + ServiceDeclaration resolverClass = loadedResolvers.get(c.getName()); + if (resolverClass != null) { + try { + return (Class)resolverClass.loadClass(); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + } else { + return resolver; + } + } + + Class resolver = resolvers.get(modelType); + if (resolver == null) { + ServiceDeclaration resolverClass = loadedResolvers.get(modelType.getName()); + if (resolverClass != null) { + try { + return (Class)resolverClass.loadClass(); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + } + } + return resolver; + } + + /** + * Dynamically load model resolvers declared under META-INF/services + */ + private void loadModelResolvers() { + if (loadedResolvers != null) + return; + loadedResolvers = new HashMap(); + + // Get the model resolver service declarations + Set modelResolverDeclarations; + try { + modelResolverDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ModelResolver.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Load model resolvers + for (ServiceDeclaration dataBindingDeclaration: modelResolverDeclarations) { + Map attributes = dataBindingDeclaration.getAttributes(); + String model = attributes.get("model"); + + loadedResolvers.put(model, dataBindingDeclaration); + } + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java new file mode 100644 index 0000000000..92cae94997 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; + +/** + * An implementation of an extensible model resolver which delegates to the + * proper resolver extension based on the class of the model to resolve. + * + * @version $Rev: 632499 $ $Date: 2008-02-29 15:59:39 -0800 (Fri, 29 Feb 2008) $ + */ +public class ExtensibleModelResolver implements ModelResolver { + private final ModelResolverExtensionPoint resolvers; + private final ModelFactoryExtensionPoint factories; + private final Contribution contribution; + private final ModelResolver defaultResolver; + private final Map, ModelResolver> resolverInstances = new HashMap, ModelResolver>(); + private Map map = new HashMap(); + + /** + * Constructs an extensible model resolver + * + * @param resolvers + * @param contribution + * @param factories + */ + @Deprecated + public ExtensibleModelResolver(Contribution contribution, + ModelResolverExtensionPoint resolvers, + ModelFactoryExtensionPoint factories, + ModelResolver defaultResolver) { + this.contribution = contribution; + this.resolvers = resolvers; + this.factories = factories; + //FIXME Remove this default resolver, this is currently used to resolve policy declarations + // but they should be handled by the contribution import/export mechanism instead of this + // defaultResolver hack. + this.defaultResolver = defaultResolver; + } + + /** + * Constructs an extensible model resolver + * + * @param resolvers + * @param contribution + * @param factories + */ + public ExtensibleModelResolver(Contribution contribution, + ModelResolverExtensionPoint resolvers, + ModelFactoryExtensionPoint factories) { + this.contribution = contribution; + this.resolvers = resolvers; + this.factories = factories; + this.defaultResolver = null; + } + + /** + * Returns the proper resolver instance based on the interfaces of the model + * If one is not available on the registry, instantiate on demand + * + * @param modelType + * @return + */ + private ModelResolver getModelResolverInstance(Class modelType) { + + // Look up a model resolver instance for the model class or + // each implemented interface + Class[] interfaces = modelType.getInterfaces(); + Class[] classes = new Class[interfaces.length + 1]; + classes[0] = modelType; + if (interfaces.length != 0) { + System.arraycopy(interfaces, 0, classes, 1, interfaces.length); + } + for (Class c : classes) { + + // Look up an existing model resolver instance + ModelResolver resolverInstance = resolverInstances.get(c); + if (resolverInstance != null) { + return resolverInstance; + } + + // We don't have an instance, lookup a model resolver class + // and instantiate it + Class resolverClass = resolvers.getResolver(c); + if (resolverClass != null) { + try { + Constructor constructor = + resolverClass + .getConstructor(new Class[] {Contribution.class, ModelFactoryExtensionPoint.class}); + if (constructor != null) { + + // Construct the model resolver instance and cache it + resolverInstance = constructor.newInstance(contribution, factories); + resolverInstances.put(c, resolverInstance); + return resolverInstance; + } + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + } + + return null; + } + + public void addModel(Object resolved) { + ModelResolver resolver = getModelResolverInstance(resolved.getClass()); + if (resolver != null) { + resolver.addModel(resolved); + } else { + map.put(resolved, resolved); + } + } + + public Object removeModel(Object resolved) { + ModelResolver resolver = getModelResolverInstance(resolved.getClass()); + if (resolver != null) { + return resolver.removeModel(resolved); + } else { + return map.remove(resolved); + } + } + + public T resolveModel(Class modelClass, T unresolved) { + ModelResolver resolver = getModelResolverInstance(unresolved.getClass()); + if (resolver != null) { + return resolver.resolveModel(modelClass, unresolved); + } else { + //FIXME Remove this default resolver, this is currently used to resolve policy declarations + // but they should be handled by the contribution import/export mechanism instead of this + // defaultResolver hack. + if (defaultResolver != null) { + Object resolved = defaultResolver.resolveModel(modelClass, unresolved); + if (resolved != null && resolved != unresolved) { + return modelClass.cast(resolved); + } + } + + Object resolved = map.get(unresolved); + if (resolved != null) { + // Return the resolved object + return modelClass.cast(resolved); + } + } + + return unresolved; + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java new file mode 100644 index 0000000000..9eaaef6e9b --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.resolver; + +/** + * A model resolver, responsible for resolving models in the scope of an + * SCA contribution. + * + * SCA Assemblies reference artifacts of a wide variety of types. These + * include: + *
    + *
  • Reference from one SCA composite to another SCA composite + *
  • Reference to PolicySet files + *
  • Reference to interface definition files, either WSDL or Java interfaces + *
  • Reference to XSD files + *
  • Reference to any of a wide variety of implementation artifact files, + * including Java classes, BPEL scripts, C++ DLLs and classes, PHP scripts + *
+ * + * In the SCA assemblies, these various artifacts are referenced using either + * QNames or logical URIs. Model resolvers are used to resolve these references + * and get the in-memory models representing the referenced artifacts. + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface ModelResolver { + + /** + * Resolve the model representing an artifact. + * + * @param modelClass the type of artifact + * @param unresolved the unresolved model + * @return the resolved model + */ + T resolveModel(Class modelClass, T unresolved); + + /** + * Add a resolved model. + * + * @param resolved The model + */ + void addModel(Object resolved); + + /** + * Remove a resolved model. + * + * @param resolved + * @return The removed model, or null if the model was not removed + */ + Object removeModel(Object resolved); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java new file mode 100644 index 0000000000..e17e815064 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.resolver; + + +/** + * An extension point for model resolvers + * + * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $ + */ +public interface ModelResolverExtensionPoint { + + /** + * Register a model resolver class using the model type as the key + * + * @param modelType The model type + * @param resolver The model resolver Class + */ + void addResolver(Class modelType, Class resolver); + + /** + * Remove the model resolver class for a specific model type + * + * @param modelType The model type + */ + void removeResolver(Class modelType); + + /** + * Retrieve a model resolver class for a specific model type + * + * @param modelType The model artifact type + * @return The model resolver Class + */ + Class getResolver(Class modelType); +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java new file mode 100644 index 0000000000..941837d862 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.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.contribution.resolver; + +import java.net.URL; + +/** + * A resource URL, which should be used to register resources + * with an ArtifactResolver and resolve these resources later. + * + * FIXME Don't use as its deprecated, use Artifact instead. + */ +@Deprecated +public class ResourceReference { + + private URL resourceURL; + private String resourceName; + + /** + * Constructs a new ResourceReference. + * + * @param resourceName Name of resource + * @param resourceURL The resource URL + */ + public ResourceReference(String resourceName, URL resourceURL) { + this.resourceURL = resourceURL; + this.resourceName = resourceName; + } + + /** + * Constructs a new ResourceReference. + * + * @param resourceName Name of resource + */ + public ResourceReference(String resourceName) { + this.resourceName = resourceName; + } + + /** + * Get the resource URL. + * + * @return The resource URL + */ + public URL getResource() { + return resourceURL; + } + + /** + * Get the resource name. + * + * @return The resource name + */ + public String getResourceName() { + return resourceName; + } + + /** + * Returns true if the resource reference is unresolved. + * + * @return Whether or not the resource has been resolved + */ + public boolean isUnresolved() { + return resourceURL == null; + } + + @Override + public int hashCode() { + return resourceName.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof ResourceReference) { + return resourceName.equals(((ResourceReference)obj).resourceName); + } else { + return false; + } + } + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java new file mode 100644 index 0000000000..b754de11fd --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.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.contribution.scanner; + +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.contribution.service.ContributionReadException; + +/** + * Interface for contribution package scanners + * + * Contribution scanners understand the format of the contribution and how to get the + * artifacts in the contribution. + * + * @version $Rev: 631891 $ $Date: 2008-02-28 00:34:05 -0800 (Thu, 28 Feb 2008) $ + */ +public interface ContributionScanner { + + /** + * Returns the type of package supported by this package scanner. + * + * @return the package type + */ + String getContributionType(); + + /** + * Returns a list of artifacts in the contribution. + * + * @param contributionURL Contribution URL + * @return List of artifact URIs + * @throws ContributionException + * @throws IOException + */ + List getArtifacts(URL contributionURL) throws ContributionReadException; + + /** + * Return the URL for an artifact in the contribution. + * + * This is needed for archives such as jar files that have specific URL schemes + * for the artifacts they contain. + * + * @param contributionURL Contribution URL + * @param artifact The relative URI for the artifact + * @return The artifact URL + */ + URL getArtifactURL(URL contributionURL, String artifact) throws ContributionReadException; + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java new file mode 100644 index 0000000000..c78872e5af --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.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.contribution.scanner; + +/** + * An extension point for contribution scanners + * + * @version $Rev: 631271 $ $Date: 2008-02-26 08:11:36 -0800 (Tue, 26 Feb 2008) $ + */ +public interface ContributionScannerExtensionPoint { + + /** + * Add a ContributionScanner using the contribution type as the key. + * + * @param scanner The contribution scanner + */ + void addContributionScanner(ContributionScanner scanner); + + /** + * Remove a ContributionScanner. + * + * @param scanner The contribution scanner + */ + void removeContributionScanner(ContributionScanner scanner); + + /** + * Returns the ContributionScanner for the given contribution type. + * + * @param contributionType The contribution type + * @return The contribution scanner + */ + ContributionScanner getContributionScanner(String contributionType); + +} \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java new file mode 100644 index 0000000000..97ddabda19 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.scanner; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Default implementation of a contribution scanner extension point. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultContributionScannerExtensionPoint implements ContributionScannerExtensionPoint { + + private Map scanners = new HashMap(); + private boolean loaded; + + public DefaultContributionScannerExtensionPoint() { + } + + public void addContributionScanner(ContributionScanner scanner) { + scanners.put(scanner.getContributionType(), scanner); + } + + public void removeContributionScanner(ContributionScanner scanner) { + scanners.remove(scanner.getContributionType()); + } + + public ContributionScanner getContributionScanner(String contentType) { + loadScanners(); + return scanners.get(contentType); + } + + private void loadScanners() { + if (loaded) + return; + + // Get the scanner service declarations + Set scannerDeclarations; + try { + scannerDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ContributionScanner.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + for (ServiceDeclaration scannerDeclaration: scannerDeclarations) { + Map attributes = scannerDeclaration.getAttributes(); + + // Load a URL artifact scanner + String contributionType = attributes.get("type"); + + // Create a scanner wrapper and register it + ContributionScanner scanner = new LazyContributionScanner(contributionType, scannerDeclaration); + addContributionScanner(scanner); + } + + loaded = true; + } + + /** + * A facade for contribution scanners. + */ + private static class LazyContributionScanner implements ContributionScanner { + + private ServiceDeclaration scannerDeclaration; + private String contributionType; + private ContributionScanner scanner; + + private LazyContributionScanner(String contributionType, ServiceDeclaration scannerDeclaration) { + this.scannerDeclaration = scannerDeclaration; + this.contributionType = contributionType; + } + + public URL getArtifactURL(URL contributionSourceURL, String artifact) throws ContributionReadException { + return getScanner().getArtifactURL(contributionSourceURL, artifact); + } + + public List getArtifacts(URL contributionSourceURL) throws ContributionReadException { + return getScanner().getArtifacts(contributionSourceURL); + } + + public String getContributionType() { + return contributionType; + } + + private ContributionScanner getScanner() { + if (scanner == null) { + try { + Class scannerClass = (Class)scannerDeclaration.loadClass(); + Constructor constructor = scannerClass.getConstructor(); + scanner = constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return scanner; + } + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java new file mode 100644 index 0000000000..6ce3e307ca --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.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.contribution.service; + +/** + * Base class for exceptions raised by contribution services. + * + * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $ + */ +public class ContributionException extends Exception { + + private static final long serialVersionUID = 4432880414927652578L; + + protected ContributionException() { + super(); + } + + protected ContributionException(String message) { + super(message); + } + + protected ContributionException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java new file mode 100644 index 0000000000..e46a6b8b40 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.service; + +import java.util.EventListener; + +import org.apache.tuscany.sca.contribution.Contribution; + +/** + * A listener interface used to listen to contribution repository events. + * + * @version $Rev: 561159 $ $Date: 2007-07-30 15:28:12 -0700 (Mon, 30 Jul 2007) $ + */ +public interface ContributionListener extends EventListener { + + /** + * Notifies the listener that a contribution has been added. + * + * @param repository The contribution repository + * @param contribution The new contribution + */ + void contributionAdded(ContributionRepository repository, Contribution contribution); + + /** + * Notifies the listener that a contribution has been removed. + * + * @param repository The contribution repository + * @param contribution The removed contribution. + */ + void contributionRemoved(ContributionRepository repository, Contribution contribution); + + /** + * Notifies the listener that a contribution has been updated. + * + * @param repository The contribution repository + * @param oldContribution The old contribution + * @param contribution The new contribution + */ + void contributionUpdated(ContributionRepository repository, Contribution oldContribution, Contribution contribution); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java new file mode 100644 index 0000000000..cbe9cf29b0 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.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.contribution.service; + +import java.util.List; + +public interface ContributionListenerExtensionPoint { + + /** + * Adds a contribution repository listener extension. + * @param listener The listener to add + */ + void addContributionListener(ContributionListener listener); + + /** + * Removes a contribution repository listener extension. + * @param listener The listener to remove + */ + void removeContributionListener(ContributionListener listener); + + /** + * Returns the contribution repository listeners. + * @return + */ + List getContributionListeners(); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java new file mode 100644 index 0000000000..eff3f59b40 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.service; + +/** + * Denotes an exception while reading artifacts inside an SCA contribution. + * + * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $ + */ +public class ContributionReadException extends ContributionException { + public static final int UNDEFINED = -1; + private static final long serialVersionUID = -7459051598906813461L; + private String resourceURI; + private int line = UNDEFINED; + private int column = UNDEFINED; + + public ContributionReadException(String message) { + super(message); + } + + public ContributionReadException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionReadException(Throwable cause) { + super(cause); + } + + /** + * Returns the location of the resource that was being read. + * + * @return the location of the resource that was being read + */ + public String getResourceURI() { + return resourceURI; + } + + /** + * Sets the location of the resource that was being read. + * + * @param resourceURI the location of the resource that was being read + */ + public void setResourceURI(String resourceURI) { + this.resourceURI = resourceURI; + } + + /** + * Returns the line inside the resource that was being read. + * @return the line inside the resource that was being read + */ + public int getLine() { + return line; + } + + /** + * Sets the line inside the resource that was being read. + * @param line the line inside the resource that was being read + */ + public void setLine(int line) { + this.line = line; + } + + /** + * Returns the column inside the resource that was being read. + * @return the column inside the resource that was being read + */ + public int getColumn() { + return column; + } + + /** + * Sets the column inside the resource that was being read. + * @param column the column inside the resource that was being read + */ + public void setColumn(int column) { + this.column = column; + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java new file mode 100644 index 0000000000..1fbfedfd97 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.contribution.service; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.sca.contribution.Contribution; + +/** + * Contribution repository + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public interface ContributionRepository { + + /** + * Get the URI of the SCA domain + * + * @return The domain URI + */ + URI getDomain(); + + /** + * Copies a contribution to the repository. + * + * @param contribution A URl pointing to the contribution being copied to + * the repository + * @param sourceURL URL of the source. this would be used to calculate the right + * filename to be stored on the repository when a inputStream is being + * provided + * @param contributionStream InputStream with the content of the + * distribution + * @return A URL pointing to the content of the contribution in the + * repository + * @throws IOException + */ + URL store(String contribution, URL sourceURL, InputStream contributionStream) throws IOException; + /** + * Copy a contribution from the source URL to the repository + * + * @param contribution A URl pointing to the contribution being copied to + * the repository + * @param sourceURL URL of the source. this would be used to calculate the right + * filename to be stored on the repository when a inputStream is being + * provided + * @return A URL pointing to the content of the contribution in the + * repository + * @throws IOException + */ + URL store(String contribution, URL sourceURL) throws IOException; + + /** + * Look up the contribution by URI + * + * @param contribution The URI of the contribution + * @return A URL pointing to the content of the contribution in the + * repository, it will be null if the contribution cannot be found + * in the repository + */ + URL find(String contribution); + + /** + * Remove a contribution from the repository + * + * @param contribution The URI of the contribution to be removed + */ + void remove(String contribution); + + /** + * Get list of URIs for all the contributions in the repository + * + * @return A list of contribution URIs + */ + List list(); + + /** + * Returns the contributions available in the repository. + * @return The list of contributions. + */ + List getContributions(); + + /** + * Adds a contribution to the repository. + * @param contribution The new contribution. + */ + void addContribution(Contribution contribution); + + /** + * Removes a contribution from the repository. + * @param contribution The contribution to remove + */ + void removeContribution(Contribution contribution); + + /** + * Updates a contribution in the repository + * @param contribution The contribution to update + */ + void updateContribution(Contribution contribution); + + /** + * Returns the contribution with the given URI. + * @param uri the URI of the contribution + * @return The contribution + */ + Contribution getContribution(String uri); + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java new file mode 100644 index 0000000000..cbfaac370f --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.service; + +/** + * Denotes a problem while resolving models inside an SCA contribution. + * + * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $ + */ +public class ContributionResolveException extends ContributionException { + private static final long serialVersionUID = -7459051598906813461L; + + public ContributionResolveException(String message) { + super(message); + } + + public ContributionResolveException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionResolveException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java new file mode 100644 index 0000000000..5ff34dea8a --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.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.contribution.service; + +/** + * Base class for runtime exceptions raised by contribution services. + * + * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $ + */ +public class ContributionRuntimeException extends RuntimeException { + private static final long serialVersionUID = 7711215366287498896L; + + protected ContributionRuntimeException() { + super(); + } + + protected ContributionRuntimeException(String message) { + super(message); + } + + protected ContributionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionRuntimeException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java new file mode 100644 index 0000000000..86f0523264 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.service; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * Service interface that manages artifacts contributed to a Tuscany runtime. + * + * @version $Rev: 637129 $ $Date: 2008-03-14 08:11:59 -0700 (Fri, 14 Mar 2008) $ + */ +public interface ContributionService { + /** + * Contribute an artifact to the SCA Domain. The type of the contribution is + * determined by the Content-Type of the resource or, if that is undefined, + * by some implementation-specific means (such as mapping an extension in + * the URL's path). + * + * @param contributionURI The URI that is used as the contribution unique ID. + * @param sourceURL The location of the resource containing the artifact + * @param modelResolver The model resolver to use to resolve models in the + * scope of this contribution + * @param storeInRepository Flag that identifies if you want to copy the + * contribution to the repository + * @return The contribution model representing the contribution + * @throws DeploymentException if there was a problem with the contribution + * @throws IOException if there was a problem reading the resource + */ + Contribution contribute(String contributionURI, URL sourceURL, boolean storeInRepository) throws ContributionException, + IOException; + + /** + * Contribute an artifact to the SCA Domain. The type of the contribution is + * determined by the Content-Type of the resource or, if that is undefined, + * by some implementation-specific means (such as mapping an extension in + * the URL's path). + * + * @param contributionURI The URI that is used as the contribution unique ID. + * @param sourceURL The location of the resource containing the artifact + * @param modelResolver The model resolver to use to resolve models in the + * scope of this contribution + * @param storeInRepository Flag that identifies if you want to copy the + * contribution to the repository + * @return The contribution model representing the contribution + * @throws DeploymentException if there was a problem with the contribution + * @throws IOException if there was a problem reading the resource + */ + Contribution contribute(String contributionURI, URL sourceURL, ModelResolver modelResolver, boolean storeInRepository) throws ContributionException, + IOException; + + /** + * Contribute an artifact to the SCA Domain. + * + * @param contributionURI The URI that is used as the contribution unique ID. + * @param sourceURL The location of the resource containing the artifact. + * This is used to identify what name should be used when storing + * the contribution on the repository + * @param modelResolver The model resolver to use to resolve models in the + * scope of this contribution + * @param contributionContent A stream containing the resource being + * contributed; the stream will not be closed but the read + * position after the call is undefined + * @return The contribution model representing the contribution + * @throws DeploymentException if there was a problem with the contribution + * @throws IOException if there was a problem reading the stream + */ + Contribution contribute(String contributionURI, URL sourceURL, InputStream contributionContent) + throws ContributionException, IOException; + + /** + * Contribute an artifact to the SCA Domain. + * + * @param contributionURI The URI that is used as the contribution unique ID. + * @param sourceURL The location of the resource containing the artifact. + * This is used to identify what name should be used when storing + * the contribution on the repository + * @param modelResolver The model resolver to use to resolve models in the + * scope of this contribution + * @param contributionContent A stream containing the resource being + * contributed; the stream will not be closed but the read + * position after the call is undefined + * @return The contribution model representing the contribution + * @throws DeploymentException if there was a problem with the contribution + * @throws IOException if there was a problem reading the stream + */ + Contribution contribute(String contributionURI, URL sourceURL, InputStream contributionContent, ModelResolver modelResolver) + throws ContributionException, IOException; + + /** + * Get the model for an installed contribution + * + * @param contribution The URI of an installed contribution + * @return The model for the contribution or null if there is no such + * contribution + */ + Contribution getContribution(String contribution); + + /** + * Adds or updates a deployment composite using a supplied composite + * ("composite by value" - a data structure, not an existing resource in the + * domain) to the contribution identified by a supplied contribution URI. + * The added or updated deployment composite is given a relative URI that + * matches the "name" attribute of the composite, with a ".composite" + * suffix. + * + * @param contribution The contribution to where + * @param composite + * @throws ContributionException + */ + void addDeploymentComposite(Contribution contribution, Composite composite) throws ContributionException; + + /** + * Remove a contribution from the SCA domain + * + * @param contribution The URI of the contribution + * @throws DeploymentException + */ + void remove(String contribution) throws ContributionException; +} \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java new file mode 100644 index 0000000000..30bfe8d1cd --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.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.contribution.service; + + +/** + * Denotes an exception while writing artifacts inside an SCA contribution. + * + * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $ + */ +public class ContributionWriteException extends ContributionException { + private static final long serialVersionUID = -7459051598906813461L; + private String resourceURI; + + public ContributionWriteException(String message) { + super(message); + } + + public ContributionWriteException(String message, Throwable cause) { + super(message, cause); + } + + public ContributionWriteException(Throwable cause) { + super(cause); + } + + /** + * Returns the location of the resource that was being written. + * + * @return the location of the resource that was being written + */ + public String getResourceURI() { + return resourceURI; + } + + /** + * Sets the location of the resource that was being written. + * + * @param resourceURI the location of the resource that was being written + */ + public void setResourceURI(String resourceURI) { + this.resourceURI = resourceURI; + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java new file mode 100644 index 0000000000..d6390c9250 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.service; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Default implementation of a contribution listener extension point. + * + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +public class DefaultContributionListenerExtensionPoint implements ContributionListenerExtensionPoint { + + private List listeners = new ArrayList(); + private boolean loadedListeners; + private ModelFactoryExtensionPoint modelFactories; + + /** + * Constructs a new DefaultContributionListenerExtensionPoint. + * + */ + public DefaultContributionListenerExtensionPoint(ModelFactoryExtensionPoint modelFactories) { + this.modelFactories = modelFactories; + } + + public void addContributionListener(ContributionListener listener) { + listeners.add(listener); + } + + public List getContributionListeners() { + loadListeners(); + return listeners; + } + + public void removeContributionListener(ContributionListener listener) { + listeners.remove(listener); + } + + /** + * Dynamically load listeners declared under META-INF/services + */ + @SuppressWarnings("unchecked") + private void loadListeners() { + if (loadedListeners) + return; + + // Get the listener service declarations + Set listenerDeclarations; + try { + listenerDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ContributionListener.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Load and instantiate the listeners + for (ServiceDeclaration listenerDeclaration: listenerDeclarations) { + ContributionListener listener; + try { + Class listenerClass = (Class)listenerDeclaration.loadClass(); + try { + Constructor constructor = listenerClass.getConstructor(ModelFactoryExtensionPoint.class); + try { + listener = constructor.newInstance(modelFactories); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException(e); + } + } catch (NoSuchMethodException e) { + listener = listenerClass.newInstance(); + } + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } catch (InstantiationException e) { + throw new IllegalArgumentException(e); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + addContributionListener(listener); + } + + loadedListeners = true; + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java new file mode 100644 index 0000000000..cba24e7b37 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.service; + +import org.apache.tuscany.sca.contribution.Contribution; + +public class ExtensibleContributionListener implements ContributionListener { + private final ContributionListenerExtensionPoint listeners; + + /** + * Default constructor receiving the listener extension point + * + * @param listeners + */ + public ExtensibleContributionListener(ContributionListenerExtensionPoint listeners) { + this.listeners = listeners; + } + + /** + * Process "contributionAdded" event to all registered listeners + */ + public void contributionAdded(ContributionRepository repository, Contribution contribution) { + for (ContributionListener listener : listeners.getContributionListeners()) { + try { + listener.contributionAdded(repository, contribution); + } catch (Exception e) { + // ignore, continue to the next listener + } + } + } + + /** + * Process "contributionRemoved" event to all registered listeners + */ + public void contributionRemoved(ContributionRepository repository, Contribution contribution) { + for (ContributionListener listener : listeners.getContributionListeners()) { + try { + listener.contributionRemoved(repository, contribution); + } catch (Exception e) { + // ignore, continue to the next listener + } + + } + } + + /** + * Process "contributionUpdated" event to all registered listeners + */ + public void contributionUpdated(ContributionRepository repository, Contribution oldContribution, Contribution contribution) { + for (ContributionListener listener : listeners.getContributionListeners()) { + try { + listener.contributionUpdated(repository, oldContribution, contribution); + } catch (Exception e) { + // ignore, continue to the next listener + } + + } + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java new file mode 100644 index 0000000000..28ea8a92ad --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.contribution.service; + +import java.net.URL; + +/** + * Provide content type for a given resource + * + * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $ + */ +public interface TypeDescriber { + /** + * Get the content type for the specified resource + * + * @param resourceURL The resource URL + * @param defaultType The default content type + * @return The content type + */ + String getType(URL resourceURL, String defaultType); +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java new file mode 100644 index 0000000000..9c6fbcce2f --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.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.contribution.service; + +import javax.xml.namespace.QName; + +/** + * Exception that indicates an element was encountered that could not be handled. + * + * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $ + */ +public class UnrecognizedElementException extends ContributionReadException { + private static final long serialVersionUID = 2549543622209829032L; + private final QName element; + + /** + * Constructor that indicates which element could not be handled. + * @param element the element that could not be handled + */ + public UnrecognizedElementException(QName element) { + super("Unrecognized element: " + element.toString()); + this.element = element; + } + + /** + * Returns the element that could not be handled. + * @return the element that could not be handled. + */ + public QName getElement() { + return element; + } +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java new file mode 100644 index 0000000000..4744fcd811 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.service; + +/** + * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain. + * The Content-Type value supplied will be returned as the message text for this exception. + * + * FIXME Don't use as it's deprecated and replaced by UnsupportedPackageTypeException. + * + * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $ + */ +@Deprecated +public class UnsupportedContentTypeException extends ContributionException { + private static final long serialVersionUID = -1831797280021355672L; + + /** + * Constructs a new UnsupportedContentTypeException. + * + * @param message + */ + public UnsupportedContentTypeException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java new file mode 100644 index 0000000000..ba549b22a9 --- /dev/null +++ b/branches/sca-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.service; + +/** + * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain. + * The Content-Type value supplied will be returned as the message text for this exception. + * + * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $ + */ +public class UnsupportedPackageTypeException extends ContributionException { + private static final long serialVersionUID = -1831797280021355672L; + + /** + * Constructs a new UnsupportedPackageTypeException. + * + * @param message + */ + public UnsupportedPackageTypeException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory new file mode 100644 index 0000000000..bcc346d9f8 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory @@ -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.contribution.DefaultContributionFactory \ No newline at end of file diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint new file mode 100644 index 0000000000..6b4d2ebdeb --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint @@ -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.contribution.DefaultModelFactoryExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint new file mode 100644 index 0000000000..9e6433ba6c --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint @@ -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.contribution.processor.DefaultContributionPostProcessorExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint new file mode 100644 index 0000000000..7609eda0d1 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint @@ -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.contribution.processor.DefaultPackageProcessorExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint new file mode 100644 index 0000000000..8ea5fc0a7e --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint @@ -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.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint new file mode 100644 index 0000000000..9d78ca93d0 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint @@ -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.contribution.processor.DefaultURLArtifactProcessorExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint new file mode 100644 index 0000000000..ae6e876df6 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint @@ -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.contribution.processor.DefaultValidationSchemaExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint new file mode 100644 index 0000000000..4bb65e55e7 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint @@ -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.contribution.resolver.DefaultModelResolverExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint new file mode 100644 index 0000000000..727f8f6ce7 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint @@ -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.contribution.scanner.DefaultContributionScannerExtensionPoint diff --git a/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint new file mode 100644 index 0000000000..6e61bebf79 --- /dev/null +++ b/branches/sca-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint @@ -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.contribution.service.DefaultContributionListenerExtensionPoint diff --git a/branches/sca-android/core-android/.classpath b/branches/sca-android/core-android/.classpath new file mode 100644 index 0000000000..a25189936b --- /dev/null +++ b/branches/sca-android/core-android/.classpath @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/core-android/.project b/branches/sca-android/core-android/.project new file mode 100644 index 0000000000..1678b1e753 --- /dev/null +++ b/branches/sca-android/core-android/.project @@ -0,0 +1,23 @@ + + tuscany-core + Parent POM defining settings that can be used across Tuscany + + tuscany-contribution + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-contribution-java + tuscany-core-spi + tuscany-sca-api + tuscany-interface-java + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/core-android/DISCLAIMER b/branches/sca-android/core-android/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/core-android/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/core-android/LICENSE b/branches/sca-android/core-android/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/core-android/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/branches/sca-android/core-android/NOTICE b/branches/sca-android/core-android/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/core-android/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/core-android/pom.xml b/branches/sca-android/core-android/pom.xml new file mode 100644 index 0000000000..0d0ee2c606 --- /dev/null +++ b/branches/sca-android/core-android/pom.xml @@ -0,0 +1,82 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-core + Apache Tuscany SCA Core Runtime + + + + org.apache.tuscany.sca + tuscany-extensibility + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-core-spi + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface-java + 2.0-incubating-SNAPSHOT + + + + org.apache.geronimo.specs + geronimo-commonj_1.1_spec + 1.0 + + + + org.codehaus.woodstox + wstx-asl + 3.2.1 + runtime + + + + cglib + cglib-nodep + 2.1_3 + + + + diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java new file mode 100644 index 0000000000..1e68564d1d --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ActivationException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.assembly; + + +/** + * Denotes an error starting the runtime + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class ActivationException extends Exception { + private static final long serialVersionUID = 8612661660934426123L; + + public ActivationException(String message) { + super(message); + } + + public ActivationException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.java new file mode 100644 index 0000000000..a96abce839 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivator.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.assembly; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.core.context.ComponentContextHelper; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Start/stop a composite + * + * @version $Rev: 575101 $ $Date: 2007-09-12 15:09:19 -0700 (Wed, 12 Sep 2007) $ + */ +public interface CompositeActivator { + /** + * Activate a composite + * @param composite + */ + void activate(Composite composite) throws ActivationException; + + /** + * Activate a component reference + * @param component + * @param ref + */ + void start(RuntimeComponent component, RuntimeComponentReference ref); + + /** + * Activate a component reference + * @param component + * @param ref + */ + void activate(RuntimeComponent component, RuntimeComponentReference ref); + + /** + * Activate a component reference + * @param component + * @param ref + */ + void activate(RuntimeComponent component, RuntimeComponentService service); + + /** + * De-activate a component reference + * @param component + * @param ref + */ + void deactivate(RuntimeComponent component, RuntimeComponentReference ref); + + /** + * De-activate a component reference + * @param component + * @param ref + */ + void deactivate(RuntimeComponent component, RuntimeComponentService service); + + /** + * Stop a composite + * @param composite + */ + void deactivate(Composite composite) throws ActivationException; + + /** + * Start a component + * @param component + */ + void start(Component component) throws ActivationException; + + /** + * Stop a component + * @param component + */ + void stop(Component component) throws ActivationException; + + /** + * Start components in a composite + * @param composite + */ + void start(Composite composite) throws ActivationException; + + /** + * Stop components in a composite + * @param composite + */ + void stop(Composite composite) throws ActivationException; + + /** + * Get the component context helper + * @return + */ + ComponentContextHelper getComponentContextHelper(); + + /** + * Get the proxy factory + * @return + */ + ProxyFactory getProxyFactory(); + + /** + * Get the java interface factory + * @return + */ + JavaInterfaceFactory getJavaInterfaceFactory(); + + ConversationManager getConversationManager(); + + /** + * Configure the runtime component with component context + * @param component + */ + void configureComponentContext(RuntimeComponent component); + + /** + * Resolve a component by URI in the domain + * @param componentURI + * @return + */ + Component resolve(String componentURI); + + /** + * Set the domain composite + * @param domainComposite + */ + void setDomainComposite(Composite domainComposite); + + /** + * Get the domain composite + * @return + */ + Composite getDomainComposite(); + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivatorImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivatorImpl.java new file mode 100644 index 0000000000..f730b2ff71 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/CompositeActivatorImpl.java @@ -0,0 +1,967 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 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.Implementation; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.context.ComponentContextHelper; +import org.apache.tuscany.sca.core.context.ComponentContextImpl; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.ConversationalScopeContainer; +import org.apache.tuscany.sca.core.scope.Scope; +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.interfacedef.java.JavaInterfaceFactory; +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.EndpointReference; +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.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.work.WorkScheduler; + +/** + * @version $Rev: 639277 $ $Date: 2008-03-20 06:02:37 -0700 (Thu, 20 Mar 2008) $ + */ +public class CompositeActivatorImpl implements CompositeActivator { + private final static Logger logger = Logger.getLogger(CompositeActivatorImpl.class.getName()); + + 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; + + private final RequestContextFactory requestContextFactory; + private final ProxyFactory proxyFactory; + private final JavaInterfaceFactory javaInterfaceFactory; + private final ConversationManager conversationManager; + + private final ComponentContextHelper componentContextHelper; + + private Composite domainComposite; + + /** + * @param assemblyFactory + * @param interfaceContractMapper + * @param workScheduler + * @param conversationManager TODO + * @param workContext + * @param wirePostProcessorRegistry + */ + public CompositeActivatorImpl(AssemblyFactory assemblyFactory, + MessageFactory messageFactory, + JavaInterfaceFactory javaInterfaceFactory, + SCABindingFactory scaBindingFactory, + InterfaceContractMapper interfaceContractMapper, + ScopeRegistry scopeRegistry, + WorkScheduler workScheduler, + RuntimeWireProcessor wireProcessor, + RequestContextFactory requestContextFactory, + ProxyFactory proxyFactory, + ProviderFactoryExtensionPoint providerFactories, + StAXArtifactProcessorExtensionPoint processors, + ConversationManager conversationManager) { + this.assemblyFactory = assemblyFactory; + this.messageFactory = messageFactory; + this.interfaceContractMapper = interfaceContractMapper; + this.scopeRegistry = scopeRegistry; + this.workScheduler = workScheduler; + this.wireProcessor = wireProcessor; + this.providerFactories = providerFactories; + this.javaInterfaceFactory = javaInterfaceFactory; + this.requestContextFactory = requestContextFactory; + this.proxyFactory = proxyFactory; + this.conversationManager = conversationManager; + this.componentContextHelper = new ComponentContextHelper(assemblyFactory, javaInterfaceFactory, processors); + } + + /** + * @see org.apache.tuscany.sca.core.assembly.CompositeActivator#activate(org.apache.tuscany.sca.runtime.RuntimeComponent, org.apache.tuscany.sca.runtime.RuntimeComponentReference) + */ + public void activate(RuntimeComponent component, RuntimeComponentReference ref) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component reference: " + component.getURI() + "#" + ref.getName()); + } + resolveTargets(ref); + for (Binding binding : ref.getBindings()) { + addReferenceBindingProvider(component, ref, binding); + } + } + + public void start(RuntimeComponent component, RuntimeComponentReference ref) { + synchronized (ref) { + resolveTargets(ref); + for (Binding binding : ref.getBindings()) { + ReferenceBindingProvider provider = ref.getBindingProvider(binding); + if (provider == null) { + provider = addReferenceBindingProvider(component, ref, binding); + } + if (provider != null) { + provider.start(); + } + addReferenceWire(component, ref, binding); + } + } + } + + public void stop(Component component, ComponentReference reference) + { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + for (Binding binding : reference.getBindings()) { + ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(binding); + if (bindingProvider != null) { + bindingProvider.stop(); + } + } + } + + public void deactivate(RuntimeComponent component, RuntimeComponentReference ref) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component reference: " + component.getURI() + "#" + ref.getName()); + } + removeReferenceWires(ref); + for (Binding binding : ref.getBindings()) { + removeReferenceBindingProvider(component, ref, binding); + } + + } + + /** + * @param component + * @param reference + * @param binding + */ + 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 class: " + binding.getClass().getName()); + } + } + + /** + * @param reference + */ + private void resolveTargets(RuntimeComponentReference reference) { + +/* Not used now that domain wires are created using the domain wire builder + // go over any targets that have not been resolved yet (as they are running on other nodes) + // and try an resolve them remotely + // TODO - this should work for any kind of wired binding but the only wireable binding + // is currently the SCA binding so we assume that + for (ComponentService service : reference.getTargets()) { + if (service.isUnresolved()) { + for (Binding binding : service.getBindings()) { + + + //binding.setURI(service.getName()); + + // TODO - we should look at all the bindings now associated with the + // unresolved target but we assume the SCA binding here as + // its currently the only wireable one + if (binding instanceof SCABinding) { + OptimizableBinding scaBinding = (OptimizableBinding)binding; + + // clone the SCA binding and fill in service details + // its cloned as each target + SCABinding clonedSCABinding = null; + try { + clonedSCABinding = (SCABinding)((OptimizableBinding)scaBinding).clone(); + // TODO - Reusing the name here to store the target name so the + // binding can be found again once the URI is set to the real endpoint + clonedSCABinding.setName(service.getName()); + clonedSCABinding.setURI(service.getName()); + // wireable binding stuff needs to go. SCA binding uses it + // currently to get to the service to work out if the service + // is resolved. + OptimizableBinding endpoint = ((OptimizableBinding)clonedSCABinding); + endpoint.setTargetComponentService(service); + //endpoint.setTargetComponent(component); - not known for unresolved target + //endpoint.setTargetBinding(serviceBinding); - not known for unresolved target + + // add the cloned SCA binding to the reference as it will be used to look up the + // provider later + reference.getBindings().remove(binding); + reference.getBindings().add(clonedSCABinding); + } catch (Exception e) { + // warning("The binding doesn't support clone: " + binding.getClass().getSimpleName(), binding); + } + } else { + + * Just leave the binding as it. It will be filled in later + * when the node resolves the targets + throw new IllegalStateException( + "Unable to create a distributed SCA binding provider for reference: " + reference + .getName() + + " and target: " + + service.getName()); + + } + } + } + } +*/ + } + + /** + * Create the runtime wires for a reference binding + * + * @param component + * @param reference + * @param binding + */ + private void addReferenceWire(Component component, ComponentReference reference, Binding binding) { + if (!(reference instanceof RuntimeComponentReference)) { + return; + } + + // create wire if binding has an endpoint + Component targetComponent = null; + ComponentService targetComponentService = null; + Binding targetBinding = null; + if (binding instanceof OptimizableBinding) { + OptimizableBinding endpoint = (OptimizableBinding)binding; + targetComponent = endpoint.getTargetComponent(); + targetComponentService = endpoint.getTargetComponentService(); + targetBinding = endpoint.getTargetBinding(); + } + + // create a forward wire, either static or dynamic + addReferenceWire(component, reference, binding, targetComponent, targetComponentService, targetBinding); + + /* + // if static forward wire (not from self-reference), try to create a static callback wire + if (targetComponentService != null && !reference.getName().startsWith("$self$.")) { + ComponentReference callbackReference = targetComponentService.getCallbackReference(); + if (callbackReference != null) { + Binding callbackBinding = null; + Binding callbackServiceBinding = null; + // select a service callback binding that can be wired back to this component + for (Binding refBinding : callbackReference.getBindings()) { + // first look for a callback binding whose name matches the target binding name + if (refBinding.getName().equals(targetBinding.getName())) { + callbackBinding = refBinding; + break; + } + } + // see if there is a matching reference callback binding + if (callbackBinding != null) { + callbackServiceBinding = reference.getCallbackService().getBinding(callbackBinding.getClass()); + } + // if there isn't an end-to-end match, try again based on target binding type + if (callbackBinding == null || callbackServiceBinding == null) { + callbackBinding = callbackReference.getBinding(targetBinding.getClass()); + if (callbackBinding != null) { + callbackServiceBinding = reference.getCallbackService().getBinding(callbackBinding.getClass()); + } + } + if (callbackBinding != null && callbackServiceBinding != null) { + // end-to-end match, so create a static callback wire as well as the static forward wire + + addReferenceWire(targetComponent, callbackReference, callbackBinding, component, reference + .getCallbackService(), callbackServiceBinding); + } else { + // no end-to-end match, so do not create a static callback wire + } + } + } + */ + } + + /** + * Create a reference wire for a forward call or a callback + * @param reference + * @param service + * @param serviceBinding + * @param component + * @param referenceBinding + */ + private RuntimeWire addReferenceWire(Component refComponent, + ComponentReference reference, + Binding refBinding, + Component serviceComponent, + ComponentService service, + Binding serviceBinding) { + RuntimeComponentReference runtimeRef = (RuntimeComponentReference)reference; + InterfaceContract bindingContract = getInterfaceContract(reference, refBinding); + + // Use the interface contract of the reference on the component type + Reference componentTypeRef = reference.getReference(); + InterfaceContract sourceContract = + componentTypeRef == null ? reference.getInterfaceContract() : componentTypeRef.getInterfaceContract(); + sourceContract = sourceContract.makeUnidirectional(false); + + EndpointReference wireSource = + new EndpointReferenceImpl((RuntimeComponent)refComponent, reference, refBinding, sourceContract); + 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); + } + + EndpointReference wireTarget = + new EndpointReferenceImpl((RuntimeComponent)serviceComponent, service, serviceBinding, bindingContract); + + RuntimeWire wire = + new RuntimeWireImpl(wireSource, wireTarget, interfaceContractMapper, workScheduler, wireProcessor, + messageFactory, conversationManager); + runtimeRef.getRuntimeWires().add(wire); + + return wire; + } + + 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, implementation); + if (policyProvider != null) { + component.addPolicyProvider(policyProvider); + } + } + + } + + private void removeImplementationProvider(RuntimeComponent component) { + component.setImplementationProvider(null); + component.getPolicyProviders().clear(); + } + + /** + * @param component + * @param service + * @param binding + */ + private ServiceBindingProvider addServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, + Binding binding) { + BindingProviderFactory providerFactory = + (BindingProviderFactory)providerFactories.getProviderFactory(binding.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ServiceBindingProvider bindingProvider = + providerFactory.createServiceBindingProvider((RuntimeComponent)component, + (RuntimeComponentService)service, + binding); + if (bindingProvider != null) { + ((RuntimeComponentService)service).setBindingProvider(binding, bindingProvider); + } + for (PolicyProviderFactory f : providerFactories.getPolicyProviderFactories()) { + PolicyProvider policyProvider = f.createServicePolicyProvider(component, service, binding); + if (policyProvider != null) { + service.addPolicyProvider(binding, policyProvider); + } + } + return bindingProvider; + } else { + throw new IllegalStateException("Provider factory not found for class: " + binding.getClass().getName()); + } + } + + 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 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(); + } + } + } + + public void start(Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + start(component); + } + } + + public void stop(Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + stop(component); + } + } + + public void start(Component component) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component: " + component.getURI()); + } + RuntimeComponent runtimeComponent = ((RuntimeComponent)component); + if(runtimeComponent.isStarted()) { + return; + } + + configureComponentContext(runtimeComponent); + + for (ComponentReference reference : component.getReferences()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + runtimeRef.setComponent(runtimeComponent); + for (Binding binding : reference.getBindings()) { + ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(binding); + if (bindingProvider != null) { + bindingProvider.start(); + } + } + } + + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component service: " + component.getURI() + "#" + service.getName()); + } + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + for (Binding binding : service.getBindings()) { + ServiceBindingProvider bindingProvider = runtimeService.getBindingProvider(binding); + if (bindingProvider != null) { + bindingProvider.start(); + } + } + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + start((Composite)implementation); + } else { + 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); + } + + /** + * @param runtimeComponent + */ + public void configureComponentContext(RuntimeComponent runtimeComponent) { + RuntimeComponentContext componentContext = + new ComponentContextImpl(this, assemblyFactory, proxyFactory, interfaceContractMapper, + requestContextFactory, javaInterfaceFactory, runtimeComponent); + runtimeComponent.setComponentContext(componentContext); + } + + /** + * Stop a component + */ + public void stop(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 (Binding binding : service.getBindings()) { + ServiceBindingProvider bindingProvider = ((RuntimeComponentService)service).getBindingProvider(binding); + if (bindingProvider != null) { + bindingProvider.stop(); + } + } + } + for (ComponentReference reference : component.getReferences()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + for (Binding binding : reference.getBindings()) { + ReferenceBindingProvider bindingProvider = runtimeRef.getBindingProvider(binding); + if (bindingProvider != null) { + bindingProvider.stop(); + } + } + } + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + stop((Composite)implementation); + } else { + ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider(); + if (implementationProvider != null) { + implementationProvider.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); + } + + /** + * Get the effective interface contract for a reference binding + * + * @param reference + * @param binding + * @return + */ + 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); + } + + /** + * Remove the runtime wires for a reference binding + * @param reference + */ + private void removeReferenceWires(ComponentReference reference) { + if (!(reference instanceof RuntimeComponentReference)) { + return; + } + // [rfeng] Comment out the following statements to avoid the on-demand activation + // RuntimeComponentReference runtimeRef = (RuntimeComponentReference)reference; + // runtimeRef.getRuntimeWires().clear(); + } + + /** + * Get the effective interface contract for the service binding + * + * @param service + * @param binding + * @return + */ + private InterfaceContract getInterfaceContract(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); + } + + /** + * Remove runtime wires for a service binding + * + * @param component + * @param service + */ + private void removeServiceWires(ComponentService service) { + if (!(service instanceof RuntimeComponentService)) { + return; + } + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + runtimeService.getRuntimeWires().clear(); + } + + /** + * Create a service wire for a forward call or a callback + * @param service + * @param serviceBinding + * @param reference + * @param component + * @param referenceBinding + */ + private RuntimeWire addServiceWire(Component serviceComponent, ComponentService service, Binding serviceBinding) { + if (!(service instanceof RuntimeComponentService)) { + return null; + } + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + + // FIXME: [rfeng] We might need a better way to get the impl interface contract + Service targetService = service.getService(); + if (targetService == null) { + targetService = service; + } + InterfaceContract targetContract = targetService.getInterfaceContract().makeUnidirectional(false); + + InterfaceContract sourceContract = getInterfaceContract(service, serviceBinding); + + EndpointReference wireSource = new EndpointReferenceImpl(null, null, serviceBinding, sourceContract); + + EndpointReference wireTarget = + new EndpointReferenceImpl((RuntimeComponent)serviceComponent, (RuntimeComponentService)service, + serviceBinding, targetContract); + + RuntimeWire wire = + new RuntimeWireImpl(wireSource, wireTarget, interfaceContractMapper, workScheduler, wireProcessor, + messageFactory, conversationManager); + runtimeService.getRuntimeWires().add(wire); + + return wire; + } + + public void activate(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; + } + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component service: " + component.getURI() + "#" + service.getName()); + } + + for (Binding binding : service.getBindings()) { + addServiceBindingProvider(component, service, binding); + addServiceWire(component, service, binding); + } + } + + 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 void addScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent); + if (scopeContainer != null && scopeContainer.getScope() == Scope.CONVERSATION) { + conversationManager.addListener((ConversationalScopeContainer)scopeContainer); + } + runtimeComponent.setScopeContainer(scopeContainer); + } + + private void removeScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = runtimeComponent.getScopeContainer(); + if(scopeContainer != null && scopeContainer.getScope() == Scope.CONVERSATION) { + conversationManager.removeListener((ConversationalScopeContainer) scopeContainer); + } + runtimeComponent.setScopeContainer(null); + } + + public void activateComponent(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((Composite) implementation); + } else if (implementation != null) { + addImplementationProvider((RuntimeComponent) component, + implementation); + addScopeContainer(component); + } + + for (ComponentService service : component.getServices()) { + activate((RuntimeComponent) component, + (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + activate((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); + } + } + + public void activate(Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component: " + component.getURI()); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + activate((Composite)implementation); + } else if (implementation != null) { + addImplementationProvider((RuntimeComponent)component, implementation); + addScopeContainer(component); + } + + for (ComponentService service : component.getServices()) { + activate((RuntimeComponent)component, (RuntimeComponentService)service); + } + + for (ComponentReference reference : component.getReferences()) { + activate((RuntimeComponent)component, (RuntimeComponentReference)reference); + } + } + } 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()) { + 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); + } + } + + /** + * @return the referenceHelper + */ + public ComponentContextHelper getComponentContextHelper() { + return componentContextHelper; + } + + /** + * @return the proxyFactory + */ + public ProxyFactory getProxyFactory() { + return proxyFactory; + } + + /** + * @return the domainComposite + */ + public Composite getDomainComposite() { + return domainComposite; + } + + /** + * @param domainComposite the domainComposite to set + */ + public void setDomainComposite(Composite domainComposite) { + this.domainComposite = domainComposite; + } + + 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; + } + + /** + * @return the javaInterfaceFactory + */ + public JavaInterfaceFactory getJavaInterfaceFactory() { + return javaInterfaceFactory; + } + + /** + * @return the conversationManager + */ + public ConversationManager getConversationManager() { + return conversationManager; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/EndpointReferenceImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/EndpointReferenceImpl.java new file mode 100644 index 0000000000..2d7cfefd16 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/EndpointReferenceImpl.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.Binding; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev: 637621 $ $Date: 2008-03-16 10:59:45 -0700 (Sun, 16 Mar 2008) $ + */ +public class EndpointReferenceImpl implements EndpointReference { + private RuntimeComponent component; + private Contract contract; + private Binding binding; + private InterfaceContract interfaceContract; + private String uri; + private EndpointReference callbackEndpoint; + private ReferenceParameters parameters = new ReferenceParametersImpl(); + + /** + * @param component + * @param contract + * @param binding + * @param interfaceContract + */ + public EndpointReferenceImpl(RuntimeComponent component, + Contract contract, + Binding binding, + InterfaceContract interfaceContract) { + super(); + this.component = component; + this.contract = contract; + this.binding = binding; + this.interfaceContract = interfaceContract; + this.uri = (component != null ? component.getURI() : "") + '/' + + (contract != null ? contract.getName() : ""); + } + + /** + * @param uri + */ + public EndpointReferenceImpl(String uri) { + super(); + this.uri = uri; + } + + public Binding getBinding() { + return binding; + } + + public void setBinding(Binding binding) { + this.binding = binding; + } + + public RuntimeComponent getComponent() { + return component; + } + + public void setComponent(RuntimeComponent component) { + this.component = component; + } + + public Contract getContract() { + return contract; + } + + public void setContract(Contract contract) { + this.contract = contract; + } + + public InterfaceContract getInterfaceContract() { + return interfaceContract; + } + + public void setInterfaceContract(InterfaceContract interfaceContract) { + this.interfaceContract = interfaceContract; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public EndpointReference getCallbackEndpoint() { + return callbackEndpoint; + } + + public void setCallbackEndpoint(EndpointReference callbackEndpoint) { + this.callbackEndpoint = callbackEndpoint; + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((uri == null) ? 0 : uri.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final EndpointReferenceImpl other = (EndpointReferenceImpl)obj; + if (uri == null) { + if (other.uri != null) { + return false; + } + } else if (!uri.equals(other.uri)) { + return false; + } + return true; + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + EndpointReferenceImpl copy = (EndpointReferenceImpl)super.clone(); + /* [nash] no need to copy callback endpoint + if (callbackEndpoint != null) { + copy.callbackEndpoint = (EndpointReference)callbackEndpoint.clone(); + } + */ + if (parameters != null) { + copy.parameters = (ReferenceParameters)parameters.clone(); + } + return copy; + } + + /** + * @return the parameters + */ + public ReferenceParameters getReferenceParameters() { + return parameters; + } + + /** + * @param parameters the parameters to set + */ + public void setReferenceParameters(ReferenceParameters parameters) { + this.parameters = parameters; + } + + public void mergeEndpoint(EndpointReference epr) { + this.component = epr.getComponent(); + this.contract = epr.getContract(); + this.binding = epr.getBinding(); + this.interfaceContract = epr.getInterfaceContract(); + this.uri = epr.getURI(); + this.callbackEndpoint = epr.getCallbackEndpoint(); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParameterProcessor.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParameterProcessor.java new file mode 100644 index 0000000000..7087df2a42 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParameterProcessor.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly; + +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.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * @version $Rev: 574648 $ $Date: 2007-09-11 10:45:36 -0700 (Tue, 11 Sep 2007) $ + */ +public class ReferenceParameterProcessor implements StAXArtifactProcessor { + private final static QName REFERENCE_PARAMETERS = + new QName("http://tuscany.apache.org/xmlns/sca/1.0", "referenceParameters", "tuscany"); + + /** + * @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) + */ + public ReferenceParameters read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + ReferenceParameters parameters = new ReferenceParametersImpl(); + parameters.setConversationID(reader.getAttributeValue(null, "conversationID")); + parameters.setCallbackID(reader.getAttributeValue(null, "callbackID")); + return parameters; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#write(java.lang.Object, javax.xml.stream.XMLStreamWriter) + */ + public void write(ReferenceParameters model, XMLStreamWriter writer) throws ContributionWriteException, + XMLStreamException { + writer.writeStartElement(REFERENCE_PARAMETERS.getPrefix(), + REFERENCE_PARAMETERS.getLocalPart(), + REFERENCE_PARAMETERS.getNamespaceURI()); + writer.writeNamespace(REFERENCE_PARAMETERS.getPrefix(), REFERENCE_PARAMETERS.getNamespaceURI()); + if (model.getConversationID() != null) { + writer.writeAttribute("conversationID", model.getConversationID().toString()); + } + 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) + */ + public void resolve(ReferenceParameters model, ModelResolver resolver) throws ContributionResolveException { + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParametersImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParametersImpl.java new file mode 100644 index 0000000000..e500e8ee20 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/ReferenceParametersImpl.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * @version $Rev: 574648 $ $Date: 2007-09-11 10:45:36 -0700 (Tue, 11 Sep 2007) $ + */ +public class ReferenceParametersImpl implements ReferenceParameters { + private Object callbackID; + private Object conversationID; + 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; + } + /** + * @return the conversationID + */ + public Object getConversationID() { + return conversationID; + } + /** + * @param conversationID the conversationID to set + */ + public void setConversationID(Object conversationID) { + this.conversationID = conversationID; + } + + /** + * @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()); + result = prime * result + ((conversationID == null) ? 0 : conversationID.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; + if (conversationID == null) { + if (other.conversationID != null) + return false; + } else if (!conversationID.equals(other.conversationID)) + return false; + return true; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java new file mode 100644 index 0000000000..5d7eab26fa --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.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.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; + +/** + * The runtime version of assembly factory + * @version $Rev: 571866 $ $Date: 2007-09-01 13:20:37 -0700 (Sat, 01 Sep 2007) $ + */ +public class RuntimeAssemblyFactory extends DefaultAssemblyFactory implements AssemblyFactory { + + public RuntimeAssemblyFactory() { + super(); + } + + @Override + public Component createComponent() { + return new RuntimeComponentImpl(); + } + + @Override + public ComponentReference createComponentReference() { + return new RuntimeComponentReferenceImpl(); + } + + @Override + public ComponentService createComponentService() { + return new RuntimeComponentServiceImpl(); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentImpl.java new file mode 100644 index 0000000000..68312e50f4 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentImpl.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.impl.ComponentImpl; +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: 634776 $ $Date: 2008-03-07 10:48:00 -0800 (Fri, 07 Mar 2008) $ + */ +public class RuntimeComponentImpl extends ComponentImpl implements RuntimeComponent, ScopedRuntimeComponent { + protected RuntimeComponentContext componentContext; + protected ImplementationProvider implementationProvider; + protected List policyProviders = new ArrayList(); + protected ScopeContainer scopeContainer; + protected boolean started; + + /** + */ + 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; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentReferenceImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentReferenceImpl.java new file mode 100644 index 0000000000..f8c80135c8 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentReferenceImpl.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +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; + +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; + } + + public RuntimeWire getRuntimeWire(Binding binding) { + for (RuntimeWire wire : getRuntimeWires()) { + if (wire.getSource().getBinding() == binding) { + 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) { + return policyProviders.get(binding); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentServiceImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentServiceImpl.java new file mode 100644 index 0000000000..0393d31d61 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeComponentServiceImpl.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.assembly; + +import java.util.ArrayList; +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.osoa.sca.ServiceRuntimeException; + +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.getTarget().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.getSource().getInterfaceContract()) { + try { + // FIXME: [rfeng] We could avoid clone() using a better comparison of the two interface contracts + wire = (RuntimeWire)wire.clone(); + wire.getSource().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.getSource().getInterfaceContract()) { + try { + // FIXME: [rfeng] We could avoid clone() using a better comparison of the two interface contracts + wire = (RuntimeWire)wire.clone(); + wire.getSource().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) { + return policyProviders.get(binding); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeWireImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeWireImpl.java new file mode 100644 index 0000000000..bd8f5e0aa1 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeWireImpl.java @@ -0,0 +1,377 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.lang.reflect.InvocationTargetException; +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.Contract; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.invocation.InvocationChainImpl; +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.RuntimeWireInvoker; +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.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.EndpointReference; +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.work.WorkScheduler; +import org.osoa.sca.ServiceRuntimeException; + +/** + * @version $Rev: 634776 $ $Date: 2008-03-07 10:48:00 -0800 (Fri, 07 Mar 2008) $ + */ +public class RuntimeWireImpl implements RuntimeWire { + private EndpointReference wireSource; + private EndpointReference wireTarget; + + private transient RuntimeWireProcessor wireProcessor; + private transient InterfaceContractMapper interfaceContractMapper; + private transient WorkScheduler workScheduler; + private transient MessageFactory messageFactory; + private transient ConversationManager conversationManager; + 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 EndpointReference lastCallback; + private RuntimeWire cachedWire; + private boolean wireReserved; + private RuntimeWireImpl clonedFrom; + + private List chains; + + /** + * @param source + * @param target + * @param interfaceContractMapper + * @param workScheduler + * @param wireProcessor + * @param messageFactory + * @param conversationManager + */ + public RuntimeWireImpl(EndpointReference source, + EndpointReference target, + InterfaceContractMapper interfaceContractMapper, + WorkScheduler workScheduler, + RuntimeWireProcessor wireProcessor, + MessageFactory messageFactory, + ConversationManager conversationManager) { + super(); + this.wireSource = source; + this.wireTarget = target; + this.interfaceContractMapper = interfaceContractMapper; + this.workScheduler = workScheduler; + this.wireProcessor = wireProcessor; + this.messageFactory = messageFactory; + this.conversationManager = conversationManager; + this.invoker = new RuntimeWireInvoker(this.messageFactory, this.conversationManager, this); + } + + public synchronized List getInvocationChains() { + if (chains == null) { + initInvocationChains(); + } + return chains; + } + + public InvocationChain getInvocationChain(Operation operation) { + for (InvocationChain chain : getInvocationChains()) { + Operation op = null; + if (wireSource.getContract() != null) { + // Reference chain + op = chain.getSourceOperation(); + } else { + // Service chain + op = chain.getTargetOperation(); + } + if (interfaceContractMapper.isCompatible(operation, op, op.getInterface().isRemotable())) { + return chain; + } + } + return null; + } + + 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); + } + + /** + * Initialize the invocation chains + */ + private void initInvocationChains() { + chains = new ArrayList(); + InterfaceContract sourceContract = wireSource.getInterfaceContract(); + InterfaceContract targetContract = wireTarget.getInterfaceContract(); + + Contract source = wireSource.getContract(); + if (source instanceof RuntimeComponentReference) { + // It's the reference wire + RuntimeComponentReference reference = (RuntimeComponentReference)wireSource.getContract(); + Binding refBinding = wireSource.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 " + + wireSource.getComponent().getURI() + + "#" + + reference.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(reference, refBinding, chain); + } + addReferenceBindingInterceptor(reference, refBinding, chain, operation); + chains.add(chain); + } + } else { + // It's the service wire + RuntimeComponentService service = (RuntimeComponentService)wireTarget.getContract(); + RuntimeComponent serviceComponent = wireTarget.getComponent(); + Binding serviceBinding = wireTarget.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 service " + + serviceComponent.getURI() + + "#" + + service.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, false); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(service, serviceBinding, chain); + } + addImplementationInterceptor(serviceComponent, service, chain, targetOperation); + chains.add(chain); + } + } + wireProcessor.process(this); + } + + public EndpointReference getSource() { + return wireSource; + } + + public EndpointReference getTarget() { + return wireTarget; + } + + public void setTarget(EndpointReference target) { + if (this.wireTarget != target) { + rebuild(); + } + this.wireTarget = target; + } + + public void rebuild() { + this.chains = null; + } + + /** + * 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.getPhase(), p.createInterceptor(operation)); + } + } + } + } + + /** + * Add the interceptor for a binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addServiceBindingInterceptor(ComponentReference 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.getPhase(), 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_BINDING, 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) { + ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider(); + if (provider != null) { + Invoker invoker = null; + invoker = provider.createInvoker((RuntimeComponentService)service, operation); + chain.addInvoker(invoker); + } + List pps = ((RuntimeComponent)component).getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(p.getPhase(), p.createInterceptor(operation)); + } + } + } + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeWireImpl copy = (RuntimeWireImpl)super.clone(); + copy.wireSource = (EndpointReference)wireSource.clone(); + copy.wireTarget = (EndpointReference)wireTarget.clone(); + copy.invoker = new RuntimeWireInvoker(copy.messageFactory, copy.conversationManager, copy); + return copy; + } + + /** + * @return the conversationManager + */ + public ConversationManager getConversationManager() { + return conversationManager; + } + + public synchronized RuntimeWire lookupCache(EndpointReference callback) { + if (lastCallback != null && callback.getURI().equals(lastCallback.getURI()) && !wireReserved) { + wireReserved = true; + return cachedWire; + } else { + return null; + } + } + + public synchronized void addToCache(EndpointReference 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; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceImpl.java new file mode 100644 index 0000000000..7019c8c7d3 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/CallableReferenceImpl.java @@ -0,0 +1,456 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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 java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.UUID; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.CompositeActivatorImpl; +import org.apache.tuscany.sca.core.assembly.EndpointReferenceImpl; +import org.apache.tuscany.sca.core.assembly.ReferenceParametersImpl; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.conversation.ConversationState; +import org.apache.tuscany.sca.core.conversation.ExtendedConversation; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.runtime.EndpointReference; +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.osoa.sca.CallableReference; +import org.osoa.sca.Conversation; +import org.osoa.sca.ServiceRuntimeException; + +/** + * Base class for implementations of service and callback references. + * + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + * @param the type of the business interface + */ +public class CallableReferenceImpl implements CallableReference, Externalizable { + static final long serialVersionUID = -521548304761848325L; + protected transient CompositeActivator compositeActivator; + protected transient ProxyFactory proxyFactory; + protected transient Class businessInterface; + protected transient Object proxy; + + // if the wire targets a conversational service this holds the conversation state + protected transient ConversationManager conversationManager; + protected transient ExtendedConversation conversation; + protected transient Object conversationID; + protected Object callbackID; // The callbackID should be serializable + + protected transient RuntimeComponent component; + protected transient RuntimeComponentReference reference; + protected transient Binding binding; + + protected String scdl; + + private transient RuntimeComponentReference clonedRef; + private transient ReferenceParameters refParams; + private transient XMLStreamReader xmlReader; + + /* + * Public constructor for Externalizable serialization/deserialization + */ + public CallableReferenceImpl() { + super(); + } + + /* + * Public constructor for use by XMLStreamReader2CallableReference + */ + public CallableReferenceImpl(XMLStreamReader xmlReader) throws Exception { + this.xmlReader = xmlReader; + resolve(); + } + + protected CallableReferenceImpl(Class businessInterface, + RuntimeComponent component, + RuntimeComponentReference reference, + Binding binding, + ProxyFactory proxyFactory, + CompositeActivator compositeActivator) { + this.proxyFactory = proxyFactory; + this.businessInterface = businessInterface; + this.component = component; + this.reference = reference; + this.binding = binding; + // FIXME: The SCA Specification is not clear how we should handle multiplicity + // for CallableReference + if (this.binding == null) { + this.binding = this.reference.getBinding(SCABinding.class); + if (this.binding == null) { + this.binding = this.reference.getBindings().get(0); + } + } + + // FIXME: Should we normalize the componentName/serviceName URI into an absolute SCA URI in the SCA binding? + // sca:component1/component11/component112/service1? + this.compositeActivator = compositeActivator; + this.conversationManager = this.compositeActivator.getConversationManager(); + RuntimeWire wire = this.reference.getRuntimeWire(this.binding); + // init(wire); + initCallbackID(); + } + + public CallableReferenceImpl(Class businessInterface, RuntimeWire wire, ProxyFactory proxyFactory) { + this.proxyFactory = proxyFactory; + this.businessInterface = businessInterface; + bind(wire); + } + + public RuntimeWire getRuntimeWire() { + try { + resolve(); + if (reference != null) { + return reference.getRuntimeWire(binding); + } else { + return null; + } + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + protected void bind(RuntimeWire wire) { + if (wire != null) { + this.component = wire.getSource().getComponent(); + this.reference = (RuntimeComponentReference)wire.getSource().getContract(); + this.binding = wire.getSource().getBinding(); + this.compositeActivator = ((ComponentContextImpl)component.getComponentContext()).getCompositeActivator(); + this.conversationManager = this.compositeActivator.getConversationManager(); + // init(wire); + initCallbackID(); + } + } + + protected void initCallbackID() { + 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 Conversation getConversation() { + try { + // resolve from XML just in case this CallableReference is the result of + // passing a CallableReference as a parameter + resolve(); + + if (conversation == null || conversation.getState() == ConversationState.ENDED) { + conversation = null; + } + return conversation; + + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public Object getCallbackID() { + try { + resolve(); + return callbackID; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * @see java.io.Externalizable#readExternal(java.io.ObjectInput) + */ + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.scdl = in.readUTF(); + } + + /** + * @throws IOException + */ + private synchronized void resolve() throws Exception { + if ((scdl != null || xmlReader != null) && component == null && reference == null) { + ComponentContextHelper componentContextHelper = ComponentContextHelper.getCurrentComponentContextHelper(); + if (componentContextHelper != null) { + CompositeActivator currentActivator = ComponentContextHelper.getCurrentCompositeActivator(); + this.compositeActivator = currentActivator; + this.conversationManager = this.compositeActivator.getConversationManager(); + Component c; + if (xmlReader != null) { + c = componentContextHelper.fromXML(xmlReader); + xmlReader = null; // OK to GC this now + } else { + c = componentContextHelper.fromXML(scdl); + scdl = null; // OK to GC this now + } + this.component = (RuntimeComponent)c; + currentActivator.configureComponentContext(this.component); + this.reference = (RuntimeComponentReference)c.getReferences().get(0); + this.reference.setComponent(this.component); + clonedRef = reference; + ReferenceParameters parameters = null; + for (Object ext : reference.getExtensions()) { + if (ext instanceof ReferenceParameters) { + parameters = (ReferenceParameters)ext; + break; + } + } + if (parameters != null) { + refParams = parameters; + this.callbackID = parameters.getCallbackID(); + + if (parameters.getConversationID() != null){ + ExtendedConversation conversation = conversationManager.getConversation(parameters.getConversationID()); + + if (conversation == null){ + conversation = conversationManager.startConversation(parameters.getConversationID()); + } + this.conversation = conversation; + } else { + this.conversation = null; + } + } + + for (Binding binding : reference.getBindings()) { + if (binding instanceof OptimizableBinding) { + String targetURI = binding.getURI(); + if (targetURI.startsWith("/")) { + targetURI = targetURI.substring(1); + } + int index = targetURI.lastIndexOf('/'); + String serviceName = ""; + if (index > -1) { + serviceName = targetURI.substring(index + 1); + targetURI = targetURI.substring(0, index); + } + Component targetComponent = compositeActivator.resolve(targetURI); + ComponentService targetService = null; + if (targetComponent != null) { + if ("".equals(serviceName)) { + targetService = ComponentContextHelper.getSingleService(targetComponent); + } else { + for (ComponentService service : targetComponent.getServices()) { + if (service.getName().equals(serviceName)) { + targetService = service; + break; + } + } + } + } + OptimizableBinding optimizableBinding = (OptimizableBinding)binding; + optimizableBinding.setTargetComponent(targetComponent); + optimizableBinding.setTargetComponentService(targetService); + if (targetService != null) { + for (Binding serviceBinding : targetService.getBindings()) { + if (serviceBinding.getClass() == binding.getClass()) { + optimizableBinding.setTargetBinding(serviceBinding); + break; + } + } + } + } + } + // FIXME: The SCA Specification is not clear how we should handle multiplicity + // for CallableReference + if (binding == null) { + binding = reference.getBinding(SCABinding.class); + if (binding == null) { + binding = reference.getBindings().get(0); + } + } + Interface i = reference.getInterfaceContract().getInterface(); + if (i instanceof JavaInterface) { + JavaInterface javaInterface = (JavaInterface)i; + if (javaInterface.isUnresolved()) { + javaInterface.setJavaClass(Thread.currentThread().getContextClassLoader() + .loadClass(javaInterface.getName())); + currentActivator.getJavaInterfaceFactory().createJavaInterface(javaInterface, + javaInterface.getJavaClass()); + } + this.businessInterface = (Class)javaInterface.getJavaClass(); + } + this.proxyFactory = currentActivator.getProxyFactory(); + } + } + } + + /** + * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput) + */ + public void writeExternal(ObjectOutput out) throws IOException { + try { + out.writeUTF(toXMLString()); + } catch (Exception e) { + // e.printStackTrace(); + throw new IOException(e.getMessage()); + } + } + + public String toXMLString() throws IOException { + if (reference != null) { + if (clonedRef == null) { + try { + clonedRef = (RuntimeComponentReference)reference.clone(); + } catch (CloneNotSupportedException e) { + // will not happen + } + } + if (refParams == null) { + refParams = new ReferenceParametersImpl(); + + // remove any existing reference parameters from the clone + Object toRemove = null; + for (Object extension : clonedRef.getExtensions()){ + if (extension instanceof ReferenceParameters){ + toRemove = extension; + } + } + + if (toRemove != null){ + clonedRef.getExtensions().remove(toRemove); + } + + // add the new reference parameter object + clonedRef.getExtensions().add(refParams); + } + refParams.setCallbackID(callbackID); + if (conversation != null){ + refParams.setConversationID(conversation.getConversationID()); + } + return ((CompositeActivatorImpl)compositeActivator).getComponentContextHelper() + .toXML(component, clonedRef); + } else { + return scdl; + } + } + + /** + * Create a callback id + * + * @return the callback id + */ + private String createCallbackID() { + return UUID.randomUUID().toString(); + } + + public void attachCallbackID(Object callbackID) { + this.callbackID = callbackID; + } + + public void attachConversationID(Object conversationID) { + this.conversationID = conversationID; + } + + public void attachConversation(ExtendedConversation conversation) { + this.conversation = conversation; + } + + + protected ReferenceParameters getReferenceParameters() { + ReferenceParameters parameters = new ReferenceParametersImpl(); + parameters.setCallbackID(callbackID); + if (getConversation() != null) { + parameters.setConversationID(conversation.getConversationID()); + } + return parameters; + } + + public EndpointReference getEndpointReference() { + try { + resolve(); + + // Use the interface contract of the reference on the component type + Reference componentTypeRef = reference.getReference(); + InterfaceContract sourceContract = + componentTypeRef == null ? reference.getInterfaceContract() : componentTypeRef.getInterfaceContract(); + sourceContract = sourceContract.makeUnidirectional(false); + EndpointReference epr = new EndpointReferenceImpl(component, reference, binding, sourceContract); + ReferenceParameters parameters = getReferenceParameters(); + epr.setReferenceParameters(parameters); + return epr; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public XMLStreamReader getXMLReader() { + return xmlReader; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextHelper.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextHelper.java new file mode 100644 index 0000000000..bcf9a366c6 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextHelper.java @@ -0,0 +1,307 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; +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.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.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.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.ReferenceParameterProcessor; +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; +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.invocation.Message; +import org.apache.tuscany.sca.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.osoa.sca.ServiceRuntimeException; + +/** + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + */ +public class ComponentContextHelper { + + private final AssemblyFactory assemblyFactory; + private final JavaInterfaceFactory javaInterfaceFactory; + private final StAXArtifactProcessorExtensionPoint staxProcessors; + + /** + * @param assemblyFactory The factory to create assembly models + * @param processors The extension point for StAX artifact processors + */ + public ComponentContextHelper(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaInterfaceFactory, + StAXArtifactProcessorExtensionPoint processors) { + this.assemblyFactory = assemblyFactory; + this.javaInterfaceFactory = javaInterfaceFactory; + this.staxProcessors = processors; + staxProcessors.addArtifactProcessor(new ReferenceParameterProcessor()); + } + + /** + * Create a self-reference for a component service + * @param component + * @param service + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + public 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); + return componentReference; + } + + /** + * @param interfaceContract + * @param businessInterface + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class businessInterface) + throws CloneNotSupportedException, InvalidInterfaceException { + Interface interfaze = interfaceContract.getInterface(); + boolean compatible = false; + 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 = (InterfaceContract)interfaceContract.clone(); + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); + } + + return interfaceContract; + } + + /** + * Bind a component reference to a component service + * @param + * @param businessInterface + * @param reference + * @param service + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + public RuntimeComponentReference bindComponentReference(Class businessInterface, + RuntimeComponentReference reference, + RuntimeComponent component, + RuntimeComponentService service) + throws CloneNotSupportedException, InvalidInterfaceException { + 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.setComponent(component); + 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 ref; + } + + public void write(Component component, ComponentReference reference, Writer writer) throws IOException { + try { + StAXArtifactProcessor processor = staxProcessors.getProcessor(Composite.class); + Composite composite = assemblyFactory.createComposite(); + composite.setName(new QName("http://tuscany.apache.org/xmlns/sca/1.0", "default")); + Component comp = assemblyFactory.createComponent(); + comp.setName("default"); + comp.setURI(component.getURI()); + composite.getComponents().add(comp); + comp.getReferences().add(reference); + + XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); + XMLStreamWriter streamWriter = outputFactory.createXMLStreamWriter(writer); + processor.write(composite, streamWriter); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + public String toXML(Component component, ComponentReference reference) throws IOException { + StringWriter writer = new StringWriter(); + write(component, reference, writer); + return writer.toString(); + } + + public RuntimeComponent read(Reader reader) throws IOException { + try { + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + XMLStreamReader streamReader = inputFactory.createXMLStreamReader(reader); + return read(streamReader); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + public RuntimeComponent read(XMLStreamReader streamReader) throws IOException { + try { + StAXArtifactProcessor processor = staxProcessors.getProcessor(Composite.class); + Composite composite = processor.read(streamReader); + RuntimeComponent component = (RuntimeComponent)composite.getComponents().get(0); + return component; + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + public Component fromXML(String xml) throws IOException { + return read(new StringReader(xml)); + } + + public Component fromXML(XMLStreamReader streamReader) throws IOException { + return read(streamReader); + } + + public static RuntimeComponent getCurrentComponent() { + Message message = ThreadMessageContext.getMessageContext(); + if (message != null) { + EndpointReference to = message.getTo(); + if (to == null) { + return null; + } + RuntimeComponent component = message.getTo().getComponent(); + return component; + } + return null; + } + + public static CompositeActivator getCurrentCompositeActivator() { + RuntimeComponent component = getCurrentComponent(); + if (component != null) { + ComponentContextImpl context = (ComponentContextImpl)component.getComponentContext(); + return context.getCompositeActivator(); + } + return null; + } + + public static ComponentContextHelper getCurrentComponentContextHelper() { + CompositeActivator activator = getCurrentCompositeActivator(); + if (activator != null) { + return activator.getComponentContextHelper(); + } + return null; + } + + /** + * @param component + */ + public static ComponentService getSingleService(Component component) { + ComponentService targetService; + List services = component.getServices(); + List regularServices = new ArrayList(); + for (ComponentService service : services) { + if (service.isCallback()) { + 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; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextImpl.java new file mode 100644 index 0000000000..9a94d6dff8 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ComponentContextImpl.java @@ -0,0 +1,397 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.IOException; +import java.io.Reader; +import java.io.Writer; + +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.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.PropertyValueFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +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.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.osoa.sca.CallableReference; +import org.osoa.sca.RequestContext; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * Implementation of ComponentContext that delegates to a ComponentContextProvider. + * + * @version $Rev: 583217 $ $Date: 2007-10-09 09:35:27 -0700 (Tue, 09 Oct 2007) $ + */ +public class ComponentContextImpl implements RuntimeComponentContext { + private final RuntimeComponent component; + + private final CompositeActivator compositeActivator; + private final RequestContextFactory requestContextFactory; + private final ProxyFactory proxyFactory; + private final AssemblyFactory assemblyFactory; + private final JavaInterfaceFactory javaInterfaceFactory; + + /** + * This is a reference to the PropertyValueFactory that is provided by the Implementation + * that can be used to get the value from a Property Object. + * + * @see #setPropertyValueFactory(PropertyValueFactory) + * @see #getProperty(Class, String) + */ + private PropertyValueFactory propertyFactory; + + public ComponentContextImpl(CompositeActivator compositeActivator, + AssemblyFactory assemblyFactory, + ProxyFactory proxyFactory, + InterfaceContractMapper interfaceContractMapper, + RequestContextFactory requestContextFactory, + JavaInterfaceFactory javaInterfaceFactory, + RuntimeComponent component) { + super(); + this.compositeActivator = compositeActivator; + this.assemblyFactory = assemblyFactory; + this.proxyFactory = proxyFactory; + this.requestContextFactory = requestContextFactory; + this.javaInterfaceFactory = javaInterfaceFactory; + this.component = component; + } + + 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())) { + return getServiceReference(businessInterface, (RuntimeComponentReference)ref, null); + } + } + throw new ServiceRuntimeException("Reference not found: " + referenceName); + } catch (ServiceRuntimeException e) { + throw e; + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + /** + * The Implementation is responsible for calling this method to set the + * PropertyValueFactory that is used to get the Property Value from + * a Tuscany Property object. + * + * @param factory The PropertyValueFactory to use + * + * @see #getProperty(Class, String) + */ + public void setPropertyValueFactory(PropertyValueFactory factory) + { + propertyFactory = factory; + } + + /** + * 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); + } + + public ServiceReference createSelfReference(Class businessInterface) { + ComponentService service = ComponentContextHelper.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(); + } else { + return new RequestContextImpl(proxyFactory); + } + } + + /** + * @param businessInterface + * @param reference + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + public ServiceReference getServiceReference(Class businessInterface, RuntimeComponentReference reference, Binding binding) { + 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(); + ref.setInterfaceContract(interfaceContract); + } + ref.setComponent(component); + return new ServiceReferenceImpl(businessInterface, component, ref, binding, proxyFactory, compositeActivator); + } 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, proxyFactory, compositeActivator); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public CallableReference 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 CallableReferenceImpl(businessInterface, component, ref, null, proxyFactory, + compositeActivator); + } 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); + return componentReference; + } + + /** + * @param interfaceContract + * @param businessInterface + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class businessInterface) + throws CloneNotSupportedException, InvalidInterfaceException { + Interface interfaze = interfaceContract.getInterface(); + boolean compatible = false; + 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; + } + + /** + * @return the compositeActivator + */ + public CompositeActivator getCompositeActivator() { + return compositeActivator; + } + + /** + * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#start(org.apache.tuscany.sca.runtime.RuntimeComponentReference) + */ + public void start(RuntimeComponentReference reference) { + compositeActivator.start(component, reference); + } + + /** + * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#read(java.io.Reader) + */ + public RuntimeComponent read(Reader reader) throws IOException { + RuntimeComponent component = compositeActivator.getComponentContextHelper().read(reader); + compositeActivator.configureComponentContext(component); + return component; + } + + /** + * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#write(org.apache.tuscany.sca.runtime.RuntimeComponentReference, java.io.Writer) + */ + public void write(RuntimeComponentReference reference, Writer writer) throws IOException { + compositeActivator.getComponentContextHelper().write(component, reference, writer); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java new file mode 100644 index 0000000000..d0fc6c969f --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.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.context; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.osoa.sca.ComponentContext; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class DefaultComponentContextFactory implements ComponentContextFactory { + private final CompositeActivator compositeActivator; + private final RequestContextFactory requestContextFactory; + private final ProxyFactory proxyFactory; + private final AssemblyFactory assemblyFactory; + private final JavaInterfaceFactory javaInterfaceFactory; + private final InterfaceContractMapper interfaceContractMapper; + + public DefaultComponentContextFactory(CompositeActivator compositeActivator, + AssemblyFactory assemblyFactory, + ProxyFactory proxyFactory, + InterfaceContractMapper interfaceContractMapper, + RequestContextFactory requestContextFactory, + JavaInterfaceFactory javaInterfaceFactory) { + super(); + this.compositeActivator = compositeActivator; + this.assemblyFactory = assemblyFactory; + this.proxyFactory = proxyFactory; + this.requestContextFactory = requestContextFactory; + this.javaInterfaceFactory = javaInterfaceFactory; + this.interfaceContractMapper = interfaceContractMapper; + } + + /** + * @see org.apache.tuscany.sca.context.ComponentContextFactory#createComponentContext(org.apache.tuscany.sca.runtime.RuntimeComponent, org.apache.tuscany.sca.context.RequestContextFactory) + */ + public ComponentContext createComponentContext(RuntimeComponent component, + RequestContextFactory requestContextFactory) { + if (requestContextFactory == null) { + requestContextFactory = this.requestContextFactory; + } + return new ComponentContextImpl(compositeActivator, assemblyFactory, proxyFactory, interfaceContractMapper, + requestContextFactory, javaInterfaceFactory, component); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/InstanceWrapper.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/InstanceWrapper.java new file mode 100644 index 0000000000..217e327184 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/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.context; + +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: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public interface InstanceWrapper { + + /** + * @return + */ + T getInstance(); + + /** + * @throws TargetInitializationException + */ + void start() throws TargetInitializationException; + + /** + * @throws TargetDestructionException + */ + void stop() throws TargetDestructionException; + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/RequestContextImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/RequestContextImpl.java new file mode 100644 index 0000000000..08e69230da --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/RequestContextImpl.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.context; + +import java.util.List; + +import javax.security.auth.Subject; + +import org.apache.tuscany.sca.core.invocation.CallbackReferenceImpl; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.EndpointReference; +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.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; +import org.osoa.sca.RequestContext; + +/** + * @version $Rev: 628809 $ $Date: 2008-02-18 08:50:37 -0800 (Mon, 18 Feb 2008) $ + */ +public class RequestContextImpl implements RequestContext { + + private ProxyFactory proxyFactory; + + public RequestContextImpl(ProxyFactory proxyFactory) { + this.proxyFactory = proxyFactory; + } + + public Subject getSecuritySubject() { + throw new UnsupportedOperationException(); + } + + public String getServiceName() { + return ThreadMessageContext.getMessageContext().getTo().getContract().getName(); + } + + @SuppressWarnings("unchecked") + public CallableReference getServiceReference() { + Message msgContext = ThreadMessageContext.getMessageContext(); + // FIXME: [rfeng] Is this the service reference matching the caller side? + EndpointReference to = msgContext.getTo(); + RuntimeComponentService service = (RuntimeComponentService) to.getContract(); + RuntimeComponent component = (RuntimeComponent) to.getComponent(); + + CallableReference callableReference = component.getComponentContext().getCallableReference(null, component, service); + ReferenceParameters parameters = msgContext.getFrom().getReferenceParameters(); + ((CallableReferenceImpl) callableReference).attachCallbackID(parameters.getCallbackID()); + if (callableReference.getConversation() != null) { + ((CallableReferenceImpl) callableReference).attachConversationID(parameters.getConversationID()); + } + return callableReference; + } + + @SuppressWarnings("unchecked") + public CB getCallback() { + CallableReference cb = getCallbackReference(); + if (cb == null) { + return null; + } + return cb.getService(); + } + + @SuppressWarnings("unchecked") + public CallableReference getCallbackReference() { + Message msgContext = ThreadMessageContext.getMessageContext(); + EndpointReference to = msgContext.getTo(); + RuntimeComponentService service = (RuntimeComponentService) to.getContract(); + 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(); + CallbackReferenceImpl ref = new CallbackReferenceImpl(javaClass, proxyFactory, wires); + //ref.resolveTarget(); + ReferenceParameters parameters = msgContext.getFrom().getReferenceParameters(); + ref.attachCallbackID(parameters.getCallbackID()); + if (ref.getConversation() != null) { + ref.attachConversationID(parameters.getConversationID()); + } + return ref; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceImpl.java new file mode 100644 index 0000000000..fde3831cdf --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceImpl.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.context; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.conversation.ConversationState; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.runtime.EndpointReference; +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.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + +/** + * Default implementation of a ServiceReference. + * + * @version $Rev: 636920 $ $Date: 2008-03-13 16:26:30 -0700 (Thu, 13 Mar 2008) $ + * @param the type of the business interface + */ +public class ServiceReferenceImpl extends CallableReferenceImpl implements ServiceReference { + private static final long serialVersionUID = 6763709434194361540L; + + protected transient Object callback; + + /* + * Public constructor for Externalizable serialization/deserialization + */ + public ServiceReferenceImpl() { + super(); + } + + /* + * Public constructor for use by XMLStreamReader2CallableReference + */ + public ServiceReferenceImpl(XMLStreamReader xmlReader) throws Exception { + super(xmlReader); + } + + /** + * @param businessInterface + * @param wire + * @param proxyFactory + */ + public ServiceReferenceImpl(Class businessInterface, RuntimeWire wire, ProxyFactory proxyFactory) { + super(businessInterface, wire, proxyFactory); + } + + public ServiceReferenceImpl(Class businessInterface, + RuntimeComponent component, + RuntimeComponentReference reference, + ProxyFactory proxyFactory, + CompositeActivator compositeActivator) { + super(businessInterface, component, reference, null, proxyFactory, compositeActivator); + } + + public ServiceReferenceImpl(Class businessInterface, + RuntimeComponent component, + RuntimeComponentReference reference, + Binding binding, + ProxyFactory proxyFactory, + CompositeActivator compositeActivator) { + super(businessInterface, component, reference, binding, proxyFactory, compositeActivator); + } + + public Object getConversationID() { + return conversationID; + } + + public void setConversationID(Object conversationID) throws IllegalStateException { + if (conversation == null || conversation.getState() != ConversationState.ENDED) { + this.conversationID = conversationID; + this.conversation = null; + } else { + throw new IllegalStateException("Trying to set the conversationId on a service reference but the state of the conversation " + + conversation.getConversationID() + + " is " + + conversation.getState()); + } + } + + public void setCallbackID(Object callbackID) { + this.callbackID = callbackID; + } + + public Object getCallback() { + return callback; + } + + public void setCallback(Object callback) { + if (callback != null && !(callback instanceof CallableReference)) { + //FIXME: need to check if callback object supports the callback interface + // returned by reference.getInterfaceContract().getCallbackInterface() + } + this.callback = callback; + } + + protected ReferenceParameters getReferenceParameters() { + ReferenceParameters parameters = super.getReferenceParameters(); + if (callback != null) { + if (callback instanceof ServiceReference) { + EndpointReference callbackRef = ((CallableReferenceImpl)callback).getEndpointReference(); + parameters.setCallbackReference(callbackRef); + } else { + EndpointReference callbackRef = getRuntimeWire().getSource().getCallbackEndpoint(); + parameters.setCallbackReference(callbackRef); + parameters.setCallbackObjectID(callback); + } + } + return parameters; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.java new file mode 100644 index 0000000000..a238ce3d4e --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationListener.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.conversation; + +/** + * Listener for the events of a conversation + * + * @version $Rev: 575101 $ $Date: 2007-09-12 15:09:19 -0700 (Wed, 12 Sep 2007) $ + */ +public interface ConversationListener { + /** + * The conversation is started + */ + void conversationStarted(ExtendedConversation conversation); + /** + * The conversation is ended + */ + void conversationEnded(ExtendedConversation conversation); + /** + * The conversation is expired + */ + void conversationExpired(ExtendedConversation conversation); +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.java new file mode 100644 index 0000000000..36a6dbcc5f --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManager.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.conversation; + +/** + * The manager of conversations + * + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + */ +public interface ConversationManager { + /** + * @param conversationID + * @return + */ + ExtendedConversation startConversation(Object conversationID); + + /** + * @param conversationID + */ + void endConversation(Object conversationID); + + /** + * @param conversationID + * @return + */ + ExtendedConversation getConversation(Object conversationID); + + /** + * @param conversationID + */ + void expireConversation(Object conversationID); + + /** + * Add a listener to this conversation + * @param listener + */ + void addListener(ConversationListener listener); + + /** + * Remove a listener from this conversation + * @param listener + */ + void removeListener(ConversationListener listener); + + /** + * @return the default max age for a conversation + */ + long getMaxAge(); + + /** + * @return the default max idle time for a conversation + */ + long getMaxIdleTime(); +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManagerImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManagerImpl.java new file mode 100644 index 0000000000..a262f311ef --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationManagerImpl.java @@ -0,0 +1,204 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.conversation; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * @version $Rev: 638875 $ $Date: 2008-03-19 08:32:44 -0700 (Wed, 19 Mar 2008) $ + */ +public class ConversationManagerImpl implements ConversationManager { + + private List listeners = Collections.synchronizedList(new ArrayList()); + private Map conversations = new ConcurrentHashMap(); + + /** + * the default max age. this is set to 1 hour + */ + private static final long DEFAULT_MAX_AGE = 60 * 60 * 1000; ; + + /** + * the default max idle time. this is set to 1 hour + */ + private static final long DEFAULT_MAX_IDLE_TIME = 60 * 60 * 1000; + + /** + * the globally used max age + */ + private final long maxAge; + + /** + * the globally used max idle time + */ + private final long maxIdleTime; + + /** + * the reaper thread + */ + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + + /** + * constructor + */ + public ConversationManagerImpl() + { + long mit = DEFAULT_MAX_IDLE_TIME; + long ma = DEFAULT_MAX_AGE; + + String aProperty; + aProperty = System.getProperty("org.apache.tuscany.sca.core.scope.ConversationalScopeContainer.MaxIdleTime"); + if (aProperty != null) { + try { + mit = (new Long(aProperty) * 1000); + } catch (NumberFormatException nfe) { + // Ignore + } + } + + aProperty = System.getProperty("org.apache.tuscany.sca.core.scope.ConversationalScopeContainer.MaxAge"); + if (aProperty != null) { + try { + ma = (new Long(aProperty) * 1000); + } catch (NumberFormatException nfe) { + // Ignore + } + } + + maxAge = ma; + maxIdleTime = mit; + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationManager#addListener(org.apache.tuscany.sca.core.conversation.ConversationListener) + */ + public void addListener(ConversationListener listener) { + listeners.add(listener); + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationManager#endConversation(org.apache.tuscany.sca.core.conversation.ExtendedConversation) + */ + public void endConversation(Object conversationID) { + ExtendedConversation conv = getConversation(conversationID); + if (conv != null) { + conv.setState(ConversationState.ENDED); + for (ConversationListener listener : listeners) { + listener.conversationEnded(conv); + } + conv.setConversationID(null); + conversations.remove(conversationID); + } else { + throw new IllegalStateException("Conversation " + conversationID + " doesn't exist."); + } + } + + public void expireConversation(Object conversationID) { + ExtendedConversation conv = getConversation(conversationID); + if (conv != null) { + for (ConversationListener listener : listeners) { + listener.conversationExpired(conv); + } + conversations.remove(conversationID); + } else { + throw new IllegalStateException("Conversation " + conversationID + " doesn't exist."); + } + + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationManager#getConversation(java.lang.Object) + */ + public ExtendedConversation getConversation(Object conversationID) { + return conversations.get(conversationID); + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationManager#removeListener(org.apache.tuscany.sca.core.conversation.ConversationListener) + */ + public void removeListener(ConversationListener listener) { + listeners.remove(listener); + } + + /** + * starts the reaper thread + */ + public void scheduleConversation(ExtendedConversationImpl aConversation, long time) + { + this.scheduler.schedule(aConversation, time, TimeUnit.MILLISECONDS); + } + + /** + * stops the reaper thread + */ + public synchronized void stopReaper() { + + // Prevent the scheduler from submitting any additional reapers, + // initiate an orderly shutdown if a reaper task is in progress. + this.scheduler.shutdown(); + } + + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationManager#startConversation(java.lang.Object) + */ + public ExtendedConversation startConversation(Object conversationID) { + + if (conversationID == null) { + conversationID = UUID.randomUUID().toString(); + } + ExtendedConversation conversation = getConversation(conversationID); + if (conversation != null && conversation.getState() != ConversationState.ENDED) { + throw new IllegalStateException(conversation + " already exists."); + } + + conversation = new ExtendedConversationImpl( + this, conversationID, ConversationState.STARTED); + conversations.put(conversationID, conversation); + for (ConversationListener listener : listeners) { + listener.conversationStarted(conversation); + } + return conversation; + } + + /** + * return the default max idle time + * @param impProvider the implementation Provider to extract any ConversationAttribute details + */ + public long getMaxIdleTime() + { + return maxIdleTime; + } + + /** + * returns the default max age + * @param impProvider the implementation Provider to extract any ConversationAttribute details + */ + public long getMaxAge(){ + return maxAge; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java new file mode 100644 index 0000000000..7d37ed496e --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ConversationState.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.conversation; + +/** + * The states of a conversation + * + * @version $Rev: 575101 $ $Date: 2007-09-12 15:09:19 -0700 (Wed, 12 Sep 2007) $ + */ +public enum ConversationState { + STARTED, ENDED, EXPIRED +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversation.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversation.java new file mode 100644 index 0000000000..f9702abced --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversation.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.core.conversation; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.osoa.sca.Conversation; + +/** + * An extended interface over org.osoa.Conversation + * + * @version $Rev: 620333 $ $Date: 2008-02-10 13:31:04 -0800 (Sun, 10 Feb 2008) $ + */ +public interface ExtendedConversation extends Conversation { + /** + * Get the state of a conversation + * @return The state + */ + ConversationState getState(); + + /** + * @param state the state to set + */ + void setState(ConversationState state); + + /** + * @param conversationID the conversationID to set + */ + void setConversationID(Object conversationID); + + + /** + * will check whether this conversation has expired and update state if it has + * @return true if it has expired + */ + boolean isExpired(); + + /** + * updates the last time this conversation was referenced + */ + void updateLastReferencedTime(); + + public void initializeConversationAttributes(RuntimeComponent targetComponent); + + + /** + * @return true if the conversational attributes have been initialized + */ + public boolean conversationalAttributesInitialized(); +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversationImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversationImpl.java new file mode 100644 index 0000000000..5b347166b5 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/conversation/ExtendedConversationImpl.java @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.conversation; + +import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * + * @version $Rev: 637931 $ $Date: 2008-03-17 08:10:55 -0700 (Mon, 17 Mar 2008) $ + */ +public class ExtendedConversationImpl implements ExtendedConversation, Runnable { + + private final ConversationManagerImpl manager; + private volatile Object conversationID; + private ConversationState state; + + /** + * syncs access to the state + */ + private final Object stateSync = new Object(); + + /** + * the maximum time a conversation can exist + */ + private long expirationTime = 0; + + /** + * the maximum time this conversation can be idle + */ + private long maxIdleTime = 0; + + /** + * the maximum age of this conversation + */ + private long maxAge = 0; + + /** + * the time that this object was created + */ + private long creationTime; + + /** + * the time that this object was last referenced + */ + private long lastReferencedTime; + + /** + * boolean to ensure expiry only occurs once + */ + private boolean expired = false; + + /** + * boolean to indicate if the conversation attributes have + * been set. In the case where a remote binding is used + * within a composite the JDKInvocationHandler can create the + * conversation but the conversationAttributes are not available + * until the conversation is retrieved by the RuntimeWireInvoker + */ + private boolean conversationAttributesInitialized = false; + + /** + * Constructor + * @param manager the conversation manager + * @param conversationID the conversation id associated with this conversation + * @param state the initial state of this conversation + * @param aMaxAge the maximum age of the conversation + * @param aMaxIdleTime the maximum idle time + */ + public ExtendedConversationImpl(ConversationManagerImpl manager, + Object conversationID, ConversationState state) { + super(); + + this.creationTime = System.currentTimeMillis(); + this.lastReferencedTime = creationTime; + this.manager = manager; + this.conversationID = conversationID; + this.state = state; + } + + /** + * will check whether this conversation has expired and update state if it has + * @return true if it has expired + */ + public boolean isExpired() { + long currentTime; + synchronized (stateSync) { + + // if the attributes haven't been initialized then + // this conversation object can't expire + if (conversationAttributesInitialized == false) { + return false; + } + + // check state first + if (state == ConversationState.EXPIRED) { + return true; + } + + // check whether the time is finished + currentTime = System.currentTimeMillis(); + if (((this.lastReferencedTime + this.maxIdleTime) <= currentTime) + || (this.expirationTime <= currentTime)) { + setState(ConversationState.EXPIRED); + return true; + } + } + scheduleNextExpiryTime(currentTime); + return false; + } + + /** + * schedule next expiry time + */ + public void scheduleNextExpiryTime(long currentTime) + { + if ((lastReferencedTime + maxIdleTime) < expirationTime){ + manager.scheduleConversation(this, (lastReferencedTime + maxIdleTime) - currentTime); + } + else{ + manager.scheduleConversation(this, expirationTime - currentTime); + } + } + /** + * updates the last time this conversation was referenced + */ + public void updateLastReferencedTime() { + this.lastReferencedTime = System.currentTimeMillis(); + if (conversationAttributesInitialized == true){ + scheduleNextExpiryTime(lastReferencedTime); + } + } + + public ConversationState getState() { + synchronized (stateSync){ + return state; + } + } + + public void end() { + manager.endConversation(conversationID); + } + + public Object getConversationID() { + return conversationID; + } + + /** + * @param state the state to set + */ + public void setState(ConversationState state) { + synchronized (stateSync){ + this.state = state; + } + } + + /** + * @param conversationID the conversationID to set + */ + public void setConversationID(Object conversationID) { + synchronized (stateSync){ + if (state != ConversationState.ENDED) { + throw new IllegalStateException("The state of conversation " + conversationID + " " + state); + } + } + this.conversationID = conversationID; + } + + /** + * @param maxAge the maximum age of this conversation + */ + public void initializeConversationAttributes(RuntimeComponent targetComponent){ + if (targetComponent != null){ + this.maxAge = getMaxIdleTime(targetComponent.getImplementationProvider()); + this.maxIdleTime = getMaxAge(targetComponent.getImplementationProvider()); + this.expirationTime = creationTime + maxAge; + this.conversationAttributesInitialized = true; + } + } + + /** + * @return true if the conversational attributes have been initialized + */ + public boolean conversationalAttributesInitialized(){ + return this.conversationAttributesInitialized; + } + + /** + * return the max idle time + * @param impProvider the implementation Provider to extract any ConversationAttribute details + */ + private long getMaxIdleTime(ImplementationProvider impProvider) + { + // Check to see if the maxIdleTime has been specified using @ConversationAttributes. + // Implementation annotated attributes are honoured first. + if ((impProvider != null) && + (impProvider instanceof ScopedImplementationProvider)) { + ScopedImplementationProvider aScopedImpl = + (ScopedImplementationProvider) impProvider; + + long maxIdleTime = aScopedImpl.getMaxIdleTime(); + if (maxIdleTime > 0) { + return maxIdleTime; + } + } + return manager.getMaxIdleTime(); + } + + /** + * returns the max age + * @param impProvider the implementation Provider to extract any ConversationAttribute details + */ + private long getMaxAge(ImplementationProvider impProvider){ + + // Check to see if the maxAge has been specified using @ConversationAttributes. + // Implementation annotated attributes are honoured first. + if ((impProvider != null) && + (impProvider instanceof ScopedImplementationProvider)) { + ScopedImplementationProvider aScopedImpl = + (ScopedImplementationProvider) impProvider; + + long maxAge = aScopedImpl.getMaxAge(); + if (maxAge > 0) { + return maxAge; + } + } + return manager.getMaxAge(); + } + + /** + * called when expiring + */ + public void run() + { + synchronized (stateSync){ + if (!expired){ + if (isExpired()) { + expired = true; + try { + manager.expireConversation(getConversationID()); + } catch (IllegalStateException ise) { + // ignore this.. this can occur if another thread has subsequently ended + // the conversation + } + } + } + } + + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/BaseEventPublisher.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/BaseEventPublisher.java new file mode 100644 index 0000000000..936717d7fd --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/BaseEventPublisher.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.event; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.sca.event.Event; +import org.apache.tuscany.sca.event.EventFilter; +import org.apache.tuscany.sca.event.EventPublisher; +import org.apache.tuscany.sca.event.RuntimeEventListener; +import org.apache.tuscany.sca.event.TrueFilter; + +/** + * Base implementation of an EventPublisher + * + * @version $Rev: 537240 $ $Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $ + */ +public abstract class BaseEventPublisher implements EventPublisher { + protected static final EventFilter TRUE_FILTER = new TrueFilter(); + protected Map> listeners; + + public void addListener(RuntimeEventListener listener) { + addListener(TRUE_FILTER, listener); + } + + public void removeListener(RuntimeEventListener listener) { + assert listener != null : "Listener cannot be null"; + synchronized (getListeners()) { + for (List currentList : getListeners().values()) { + for (RuntimeEventListener current : currentList) { + if (current == listener) { + currentList.remove(current); + return; + } + } + } + } + } + + public void addListener(EventFilter filter, RuntimeEventListener listener) { + assert listener != null : "Listener cannot be null"; + synchronized (getListeners()) { + List list = getListeners().get(filter); + if (list == null) { + list = new CopyOnWriteArrayList(); + listeners.put(filter, list); + } + list.add(listener); + } + } + + public void publish(Event event) { + assert event != null : "Event object was null"; + for (Map.Entry> entry : getListeners().entrySet()) { + if (entry.getKey().match(event)) { + for (RuntimeEventListener listener : entry.getValue()) { + listener.onEvent(event); + } + } + } + } + + protected Map> getListeners() { + if (listeners == null) { + listeners = new ConcurrentHashMap>(); + } + return listeners; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStart.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStart.java new file mode 100644 index 0000000000..7770c9133b --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStart.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.event; + +import java.net.URI; + +import org.apache.tuscany.sca.event.Event; + +/** + * Propagated when a component starts + * + * @version $$Rev: 639271 $$ $$Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $$ + */ +public class ComponentStart implements Event { + + private Object source; + private URI uri; + + /** + * Creates a component start event + * + * @param source the source of the event + * @param componentURI the URI of the component being started + */ + public ComponentStart(Object source, URI componentURI) { + this.source = source; + this.uri = componentURI; + } + + public URI getComponentURI() { + return uri; + } + + public Object getSource() { + return source; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStop.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStop.java new file mode 100644 index 0000000000..195971dc8f --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ComponentStop.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.event; + +import java.net.URI; + +import org.apache.tuscany.sca.event.Event; + +/** + * Propagated when a component stops + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class ComponentStop implements Event { + + private Object source; + private URI uri; + + /** + * Creates a component stop event + * + * @param source the source of the event + * @param componentUri the composite component associated the component being stopped + */ + public ComponentStop(Object source, URI componentUri) { + this.source = source; + this.uri = componentUri; + } + + public URI getComponentURI() { + return uri; + } + + public Object getSource() { + return source; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationEnd.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationEnd.java new file mode 100644 index 0000000000..99ec0d2bef --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationEnd.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.event; + +import org.apache.tuscany.sca.event.Event; + + + +/** + * Propagated when a conversation is expired + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class ConversationEnd implements Event { + + private Object source; + private Object id; + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the conversation being ended + */ + public ConversationEnd(Object source, Object id) { + this.source = source; + this.id = id; + } + + public Object getSource() { + return source; + } + + public Object getConversationID() { + return id; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationStart.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationStart.java new file mode 100644 index 0000000000..c80dc19676 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/ConversationStart.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.event; + +import org.apache.tuscany.sca.event.Event; + + +/** + * Propagated when a conversation has started + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class ConversationStart implements Event { + + private Object source; + private Object id; + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the conversation being started + */ + public ConversationStart(Object source, Object id) { + this.source = source; + this.id = id; + } + + public Object getSource() { + return source; + } + + public Object getConversationID() { + return id; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionEnd.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionEnd.java new file mode 100644 index 0000000000..4bbadff869 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionEnd.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.event; + +import org.apache.tuscany.sca.event.Event; + + + +/** + * Propagated when an HTTP-based session is expired + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class HttpSessionEnd implements Event { + + private Object source; + private Object id; + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpSessionEnd(Object source, Object id) { + this.source = source; + this.id = id; + } + + public Object getSource() { + return source; + } + + public Object getSessionID() { + return id; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionStart.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionStart.java new file mode 100644 index 0000000000..100bf05d32 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/HttpSessionStart.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.event; + +import org.apache.tuscany.sca.event.Event; + + +/** + * Propagated when an HTTP-based session has started + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class HttpSessionStart implements Event { + + private Object source; + private Object id; + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being started + */ + public HttpSessionStart(Object source, Object id) { + this.source = source; + this.id = id; + } + + public Object getSource() { + return source; + } + + public Object getSessionID() { + return id; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestEnd.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestEnd.java new file mode 100644 index 0000000000..56df7d10a9 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestEnd.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.event; + +import org.apache.tuscany.sca.event.Event; + +/** + * Propagated when a request completes or is ended + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class RequestEnd implements Event { + + private Object source; + + /** + * Creates a new event + * + * @param source the source of the event + */ + public RequestEnd(Object source) { + this.source = source; + } + + public Object getSource() { + return source; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestStart.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestStart.java new file mode 100644 index 0000000000..bacd652402 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/event/RequestStart.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.event; + +import org.apache.tuscany.sca.event.Event; + +/** + * Propagated when a request is started in the runtime + * + * @version $$Rev: 537240 $$ $$Date: 2007-05-11 10:35:03 -0700 (Fri, 11 May 2007) $$ + */ +public class RequestStart implements Event { + + private Object source; + + /** + * Creates a new event + * + * @param source the source of the event + */ + public RequestStart(Object source) { + this.source = source; + } + + public Object getSource() { + return source; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java new file mode 100644 index 0000000000..da8ce41ce7 --- /dev/null +++ b/branches/sca-android/core-android/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: 567617 $ $Date: 2007-08-20 02:29:15 -0700 (Mon, 20 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java new file mode 100644 index 0000000000..9b5e564081 --- /dev/null +++ b/branches/sca-android/core-android/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: 567617 $ $Date: 2007-08-20 02:29:15 -0700 (Mon, 20 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java new file mode 100644 index 0000000000..96ce410539 --- /dev/null +++ b/branches/sca-android/core-android/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.Binding; +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.osoa.sca.CallableReference; + +/** + * Uses a wire to return a CallableReference + * + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + */ +public class CallableReferenceObjectFactory implements ObjectFactory> { + private Class businessInterface; + private RuntimeComponent component; + private RuntimeComponentReference reference; + private Binding binding; + + /** + * 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, + Binding binding) { + this.businessInterface = businessInterface; + this.component = component; + this.reference = reference; + this.binding = binding; + } + + public CallableReference getInstance() throws ObjectCreationException { + return component.getComponentContext().getServiceReference(businessInterface, reference, binding); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java new file mode 100644 index 0000000000..40ee01a434 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +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.ReferenceParameters; +import org.osoa.sca.NoRegisteredCallbackException; + +/** + * 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: 608822 $ $Date: 2008-01-04 04:59:56 -0800 (Fri, 04 Jan 2008) $ + */ +public class CallbackInterfaceInterceptor implements Interceptor { + private Invoker next; + + public CallbackInterfaceInterceptor() { + } + + public Message invoke(Message msg) { + 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceImpl.java new file mode 100644 index 0000000000..dfc3dcc95d --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceImpl.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.Binding; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.core.assembly.RuntimeWireImpl; +import org.apache.tuscany.sca.core.context.CallableReferenceImpl; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.EndpointReference; +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; + +/** + * Returns proxy instance for a wire callback + * + * @version $Rev: 576055 $ $Date: 2007-09-16 08:11:45 +0100 (Sun, 16 Sep 2007) $ + */ +public class CallbackReferenceImpl extends CallableReferenceImpl { + private RuntimeWire wire; + private List wires; + private EndpointReference resolvedEndpoint; + private Object convID; + + public CallbackReferenceImpl(Class interfaze, ProxyFactory proxyFactory, List wires) { + 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().getURI()); + } + resolvedEndpoint = getCallbackEndpoint(msgContext); + convID = msgContext.getFrom().getReferenceParameters().getConversationID(); + callbackID = msgContext.getFrom().getReferenceParameters().getCallbackID(); + } + + @Override + protected Object createProxy() throws Exception { + return proxyFactory.createCallbackProxy(this); + } + + protected RuntimeWire getCallbackWire() { + if (resolvedEndpoint == null) { + return null; + } else { + return cloneAndBind(wire); + } + } + + protected Object getConvID() { + return convID; + } + + protected EndpointReference getResolvedEndpoint() { + return resolvedEndpoint; + } + + private RuntimeWire selectCallbackWire(Message msgContext) { + // look for callback binding with same name as service binding + EndpointReference 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.getSource().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.getSource().getBinding().getClass() == to.getBinding().getClass()) { + return wire; + } + } + + // no suitable callback wire was found + return null; + } + + /** + * @param msgContext + */ + private static EndpointReference getCallbackEndpoint(Message msgContext) { + EndpointReference from = msgContext.getFrom(); + if (from == null) { + return null; + } + return from.getReferenceParameters().getCallbackReference(); + } + + private RuntimeWire cloneAndBind(RuntimeWire wire) { + RuntimeWire boundWire = null; + if (resolvedEndpoint != null) { + boundWire = ((RuntimeWireImpl)wire).lookupCache(resolvedEndpoint); + if (boundWire != null) { + return boundWire; + } + try { + Contract contract = resolvedEndpoint.getContract(); + RuntimeComponentReference ref = null; + if (contract == null) { + boundWire = (RuntimeWire)wire.clone(); + + } else if (contract instanceof RuntimeComponentReference) { + ref = (RuntimeComponentReference)contract; + boundWire = ref.getRuntimeWire(resolvedEndpoint.getBinding()); + + } else { // contract instanceof RuntimeComponentService + ref = bind((RuntimeComponentReference)wire.getSource().getContract(), + resolvedEndpoint.getComponent(), + (RuntimeComponentService)contract); + boundWire = ref.getRuntimeWires().get(0); + } + configureWire(boundWire); + ((RuntimeWireImpl)wire).addToCache(resolvedEndpoint, boundWire); + } catch (CloneNotSupportedException e) { + // will not happen + } + } + return boundWire; + } + + private static RuntimeComponentReference bind(RuntimeComponentReference reference, + RuntimeComponent component, + RuntimeComponentService service) throws CloneNotSupportedException { + RuntimeComponentReference ref = (RuntimeComponentReference)reference.clone(); + 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 ref; + } + + private void configureWire(RuntimeWire wire) { + // need to set the endpoint on the binding also so that when the chains are created next + // the sca binding can decide whether to provide local or remote invokers. + // TODO - there is a problem here though in that I'm setting a target on a + // binding that may possibly be trying to point at two things in the multi threaded + // case. Need to confirm the general model here and how the clone and bind part + // is intended to work + Binding binding = wire.getSource().getBinding(); + binding.setURI(resolvedEndpoint.getURI()); + + // also need to set the target contract as it varies for the sca binding depending on + // whether it is local or remote + RuntimeComponentReference ref = (RuntimeComponentReference)wire.getSource().getContract(); + wire.getTarget().setInterfaceContract(ref.getBindingProvider(binding).getBindingInterfaceContract()); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java new file mode 100644 index 0000000000..3ccd357db7 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.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 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; +import org.osoa.sca.CallableReference; + +/** + * Uses a wire to return a CallableReference + * + * @version $Rev: 574648 $ $Date: 2007-09-11 18:45:36 +0100 (Tue, 11 Sep 2007) $ + */ +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 CallableReference getInstance() throws ObjectCreationException { + return new CallbackReferenceImpl(businessInterface, proxyFactory, wires); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java new file mode 100644 index 0000000000..e41b18c290 --- /dev/null +++ b/branches/sca-android/core-android/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: 596162 $ $Date: 2007-11-18 15:50:50 -0800 (Sun, 18 Nov 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java new file mode 100644 index 0000000000..c201b37a51 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.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.CallableReferenceImpl; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + +/** + * The implementation of a wire service that uses cglib dynamic proxies + * + * @version $Rev: 628809 $ $Date: 2008-02-18 08:50:37 -0800 (Mon, 18 Feb 2008) $ + */ +@SuppressWarnings("unused") +public class CglibProxyFactory implements ProxyFactory { + private MessageFactory messageFactory; + + public CglibProxyFactory() { + this(new MessageFactoryImpl(), new InterfaceContractMapperImpl()); + } + + 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(CallableReference callableReference) throws ProxyCreationException { + Enhancer enhancer = new Enhancer(); + Class interfaze = callableReference.getBusinessInterface(); + enhancer.setSuperclass(interfaze); + enhancer.setCallback(new CglibMethodInterceptor(callableReference)); + Object proxy = enhancer.create(); + ((CallableReferenceImpl)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 { + CallbackReferenceImpl callbackReference = new CallbackReferenceImpl(interfaze, this, wires); + return createCallbackProxy(callbackReference); + } + + /** + * create the callback proxy with cglib. use the same + * JDKCallbackInvocationHandler as JDKProxyService. + */ + public T createCallbackProxy(CallbackReferenceImpl 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(CallableReference callableReference) { + invocationHandler = new JDKInvocationHandler(messageFactory, callableReference); + } + + public CglibMethodInterceptor(CallbackReferenceImpl 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java new file mode 100644 index 0000000000..3fa636ed26 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; + +public class DefaultProxyFactoryExtensionPoint implements ProxyFactoryExtensionPoint { + private InterfaceContractMapper interfaceContractMapper; + private MessageFactory messageFactory; + + private ProxyFactory interfaceFactory; + private ProxyFactory classFactory; + + public DefaultProxyFactoryExtensionPoint() { + this(new MessageFactoryImpl(), new InterfaceContractMapperImpl()); + } + + public DefaultProxyFactoryExtensionPoint(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.interfaceContractMapper = mapper; + this.messageFactory = messageFactory; + interfaceFactory = new JDKProxyFactory(messageFactory, mapper); + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint#getClassProxyFactory() + */ + public ProxyFactory getClassProxyFactory() { + return classFactory; + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint#getInterfaceProxyFactory() + */ + public ProxyFactory getInterfaceProxyFactory() { + return interfaceFactory; + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint#setClassProxyFactory(org.apache.tuscany.sca.core.invocation.ProxyFactory) + */ + public void setClassProxyFactory(ProxyFactory factory) { + this.classFactory = factory; + + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint#setInterfaceProxyFactory(org.apache.tuscany.sca.core.invocation.ProxyFactory) + */ + public void setInterfaceProxyFactory(ProxyFactory factory) { + this.interfaceFactory = factory; + + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#cast(java.lang.Object) + */ + @SuppressWarnings("unchecked") + public > R cast(B target) throws IllegalArgumentException { + 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 { + if (interfaze.isInterface()) { + return interfaceFactory.createCallbackProxy(interfaze, wires); + } else { + return classFactory.createCallbackProxy(interfaze, wires); + } + } + + public T createProxy(CallableReference callableReference) throws ProxyCreationException { + if (callableReference.getBusinessInterface().isInterface()) { + return interfaceFactory.createProxy(callableReference); + } else { + return classFactory.createProxy(callableReference); + } + } + + public T createCallbackProxy(CallbackReferenceImpl callbackReference) throws ProxyCreationException { + 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 { + 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) { + return interfaceFactory.isProxyClass(clazz) || (classFactory != null && classFactory.isProxyClass(clazz)); + } + + /** + * @return the interfaceContractMapper + */ + public InterfaceContractMapper getInterfaceContractMapper() { + return interfaceContractMapper; + } + + /** + * @return the messageFactory + */ + public MessageFactory getMessageFactory() { + return messageFactory; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java new file mode 100644 index 0000000000..a5f9cdc84a --- /dev/null +++ b/branches/sca-android/core-android/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: 538423 $ $Date: 2007-05-15 21:11:06 -0700 (Tue, 15 May 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/InvocationChainImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/InvocationChainImpl.java new file mode 100644 index 0000000000..5c9ae8c706 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/InvocationChainImpl.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +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.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +import org.apache.tuscany.sca.invocation.Phase; + +/** + * Default implementation of an invocation chain + * + * @version $Rev: 634778 $ $Date: 2008-03-07 10:58:16 -0800 (Fri, 07 Mar 2008) $ + */ +public class InvocationChainImpl implements InvocationChain { + private Operation sourceOperation; + private Operation targetOperation; + private List nodes = new ArrayList(); + + // FIXME: Not a good practice to use static reference + private final static PhaseManager phaseManager = new PhaseManager(); + private boolean forReference; + private boolean allowsPassByReference; + + public InvocationChainImpl(Operation sourceOperation, Operation targetOperation, boolean forReference) { + assert sourceOperation != null; + assert targetOperation != null; + this.targetOperation = targetOperation; + this.sourceOperation = sourceOperation; + this.forReference = forReference; + } + + public Operation getTargetOperation() { + return targetOperation; + } + + public void setTargetOperation(Operation operation) { + this.targetOperation = operation; + } + + public void addInterceptor(Interceptor interceptor) { + String phase = forReference ? Phase.REFERENCE : Phase.SERVICE; + addInterceptor(phase, interceptor); + } + + public void addInvoker(Invoker invoker) { + String phase = forReference ? Phase.REFERENCE_BINDING : Phase.IMPLEMENTATION; + addInvoker(phase, invoker); + } + + public Invoker getHeadInvoker() { + return nodes.isEmpty() ? null : nodes.get(0).getInvoker(); + } + + public Invoker getTailInvoker() { + return nodes.isEmpty() ? null : nodes.get(nodes.size() - 1).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(int index, Interceptor interceptor) { + addInterceptor(interceptor); + } + + 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; + } + + public String toString() { + return "(" + phaseIndex + ")" + invoker; + } + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKCallbackInvocationHandler.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKCallbackInvocationHandler.java new file mode 100644 index 0000000000..4bc18fe80a --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKCallbackInvocationHandler.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.core.assembly.RuntimeWireImpl; +import org.apache.tuscany.sca.core.context.CallableReferenceImpl; +import org.apache.tuscany.sca.core.conversation.ConversationState; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.NoRegisteredCallbackException; +import org.osoa.sca.ServiceRuntimeException; + +/** + * Responsible for dispatching to a callback through a wire.

TODO cache + * target invoker + * + * @version $Rev: 638875 $ $Date: 2008-03-19 08:32:44 -0700 (Wed, 19 Mar 2008) $ + */ +public class JDKCallbackInvocationHandler extends JDKInvocationHandler { + private static final long serialVersionUID = -3350283555825935609L; + + public JDKCallbackInvocationHandler(MessageFactory messageFactory, CallbackReferenceImpl 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 = ((CallbackReferenceImpl)callableReference).getCallbackWire(); + if (wire == null) { + //FIXME: need better exception + throw new ServiceRuntimeException("No callback wire found"); + } + + // set the conversational state based on the interface that + // is specified for the reference that this wire belongs to + initConversational(wire); + + // set the conversation id into the conversation object. This is + // a special case for callbacks as, unless otherwise set manually, + // the callback should use the same conversation id as was received + // on the incoming call to this component + if (conversational) { + + if (conversation == null || conversation.getState() == ConversationState.ENDED) { + conversation = null; + } + Object convID = conversation == null ? null : conversation.getConversationID(); + + // create a conversation id if one doesn't exist + // already, i.e. the conversation is just starting + if (convID == null) { + convID = ((CallbackReferenceImpl)callableReference).getConvID(); + if (convID != null) { + conversation = ((RuntimeWireImpl)wire).getConversationManager().getConversation(convID); + if (callableReference != null) { + ((CallableReferenceImpl)callableReference).attachConversation(conversation); + } + } + } + } + + setEndpoint(((CallbackReferenceImpl)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.getSource()); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof NoRegisteredCallbackException) { + throw t; + } + throw e; + } finally { + // allow the cloned wire to be reused by subsequent callbacks + ((RuntimeWireImpl)wire).releaseWire(); + } + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java new file mode 100644 index 0000000000..3dfc435e00 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java @@ -0,0 +1,489 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.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 java.util.UUID; + +import org.apache.tuscany.sca.core.assembly.RuntimeWireImpl; +import org.apache.tuscany.sca.core.context.CallableReferenceImpl; +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.conversation.ConversationState; +import org.apache.tuscany.sca.core.conversation.ExtendedConversation; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +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.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ConversationEndedException; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + */ +public class JDKInvocationHandler implements InvocationHandler, Serializable { + private static final long serialVersionUID = -3366410500152201371L; + + protected boolean conversational; + protected ExtendedConversation conversation; + protected MessageFactory messageFactory; + protected EndpointReference source; + protected EndpointReference target; + protected RuntimeWire wire; + protected CallableReference 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, CallableReference callableReference) { + this.messageFactory = messageFactory; + this.callableReference = callableReference; + if (callableReference != null) { + this.businessInterface = callableReference.getBusinessInterface(); + this.conversation = (ExtendedConversation)callableReference.getConversation(); + this.wire = ((CallableReferenceImpl)callableReference).getRuntimeWire(); + if (wire != null) { + init(wire); + } + } + } + + protected void init(RuntimeWire wire) { + 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); + } + } + + protected void initConversational(RuntimeWire wire) { + InterfaceContract contract = wire.getSource().getInterfaceContract(); + this.conversational = contract.getInterface().isConversational(); + } + + protected Object getCallbackID() { + if (callableReference != null) { + return callableReference.getCallbackID(); + } else { + return null; + } + } + + protected Object getConversationID() { + if (callableReference != null && callableReference instanceof ServiceReference) { + return ((ServiceReference)callableReference).getConversationID(); + } else { + return null; + } + } + + protected Object getCallbackObject() { + if (callableReference != null && callableReference instanceof ServiceReference) { + return ((ServiceReference)callableReference).getCallback(); + } 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"); + } + InvocationChain chain = getInvocationChain(method, wire); + if (chain == null) { + throw new IllegalArgumentException("No matching operation is found: " + method); + } + + // 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(EndpointReference 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.getTarget()); + } + Invoker headInvoker = chain.getHeadInvoker(); + Operation operation = chain.getTargetOperation(); + msg.setOperation(operation); + msg.setBody(args); + + Message msgContext = ThreadMessageContext.getMessageContext(); + Object currentConversationID = msgContext.getFrom().getReferenceParameters().getConversationID(); + + conversationPreinvoke(msg, wire); + handleCallback(msg, wire, currentConversationID); + ThreadMessageContext.setMessageContext(msg); + try { + // dispatch the wire down the chain and get the response + Message resp = headInvoker.invoke(msg); + Object body = resp.getBody(); + if (resp.isFault()) { + throw (Throwable)body; + } + return body; + } finally { + conversationPostInvoke(msg, wire); + ThreadMessageContext.setMessageContext(msgContext); + } + } + + /** + * @param msg + * @param wire + * @param interfaze + * @throws TargetResolutionException + */ + private void handleCallback(Message msg, RuntimeWire wire, Object currentConversationID) + throws TargetResolutionException { + ReferenceParameters parameters = msg.getFrom().getReferenceParameters(); + parameters.setCallbackID(getCallbackID()); + if (msg.getFrom() == null || msg.getFrom().getCallbackEndpoint() == null) { + return; + } + + 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.getOperation().getInterface(); + if (callbackObject != null) { + if (callbackObject instanceof ServiceReference) { + EndpointReference callbackRef = ((CallableReferenceImpl)callbackObject).getEndpointReference(); + parameters.setCallbackReference(callbackRef); + } else { + if (interfaze != null) { + if (!interfaze.isConversational()) { + throw new IllegalArgumentException( + "Callback object for stateless callback is not a ServiceReference"); + } else { + 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 + */ + private void conversationPreinvoke(Message msg, RuntimeWire wire) { + if (!conversational) { + // Not conversational or the conversation has been started + return; + } + + ConversationManager conversationManager = ((RuntimeWireImpl)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.getTarget().getComponent() != null){ + conversation.initializeConversationAttributes(wire.getTarget().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 RuntimeWireInvker will take care of this + if (wire.getTarget().getComponent() != null){ + conversation.updateLastReferencedTime(); + } + + msg.getFrom().getReferenceParameters().setConversationID(conversation.getConversationID()); + + } + + /** + * Post-invoke for the conversation handling + * @param wire + * @param operation + * @throws TargetDestructionException + */ + @SuppressWarnings("unchecked") + private void conversationPostInvoke(Message msg, RuntimeWire wire) 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) && (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 = wire.getSource().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 + */ + private Object createConversationID() { + if (getConversationID() != null) { + return getConversationID(); + } else { + return UUID.randomUUID().toString(); + } + } + + /** + * @return the callableReference + */ + public CallableReference getCallableReference() { + return callableReference; + } + + /** + * @param callableReference the callableReference to set + */ + public void setCallableReference(CallableReference callableReference) { + this.callableReference = 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKProxyFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKProxyFactory.java new file mode 100644 index 0000000000..4380dc18ab --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/JDKProxyFactory.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.InvocationHandler; +import java.lang.reflect.Proxy; +import java.util.List; + +import org.apache.tuscany.sca.core.context.CallableReferenceImpl; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + +/** + * the default implementation of a wire service that uses JDK dynamic proxies + * + * @version $$Rev: 628809 $$ $$Date: 2007-04-11 18:59:43 -0700 (Wed, 11 Apr + * 2007) $$ + */ +public class JDKProxyFactory implements ProxyFactory { + protected InterfaceContractMapper contractMapper; + private MessageFactory messageFactory; + + public JDKProxyFactory() { + this(new MessageFactoryImpl(), new InterfaceContractMapperImpl()); + } + + 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(CallableReference callableReference) throws ProxyCreationException { + assert callableReference != null; + Class interfaze = callableReference.getBusinessInterface(); + InvocationHandler handler = new JDKInvocationHandler(messageFactory, callableReference); + ClassLoader cl = interfaze.getClassLoader(); + Object proxy = Proxy.newProxyInstance(cl, new Class[] {interfaze}, handler); + ((CallableReferenceImpl)callableReference).setProxy(proxy); + return interfaze.cast(proxy); + } + + public T createCallbackProxy(Class interfaze, List wires) throws ProxyCreationException { + CallbackReferenceImpl callbackReference = new CallbackReferenceImpl(interfaze, this, wires); + return createCallbackProxy(callbackReference); + } + + public T createCallbackProxy(CallbackReferenceImpl callbackReference) throws ProxyCreationException { + assert callbackReference != null; + Class interfaze = callbackReference.getBusinessInterface(); + InvocationHandler handler = new JDKCallbackInvocationHandler(messageFactory, callbackReference); + ClassLoader cl = interfaze.getClassLoader(); + Object proxy = 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); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageFactoryImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageFactoryImpl.java new file mode 100644 index 0000000000..786e91a788 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/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; + +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; + +/** + * Implementation of MessageFactory. + * + * @version $Rev: 537327 $ $Date: 2007-05-11 20:18:05 -0700 (Fri, 11 May 2007) $ + */ +public class MessageFactoryImpl implements MessageFactory { + + public Message createMessage() { + return new MessageImpl(); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageImpl.java new file mode 100644 index 0000000000..fb476c3c7b --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/MessageImpl.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.Hashtable; +import java.util.Map; + +import org.apache.tuscany.sca.core.assembly.EndpointReferenceImpl; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.EndpointReference; + +/** + * The default implementation of a message flowed through a wire during an invocation + * + * @version $Rev $Date + */ +public class MessageImpl implements Message { + private Object body; + private Object messageID; + private boolean isFault; + private Operation operation; + private Map qosContext = new Hashtable(); + + private EndpointReference from; + private EndpointReference to; + + public MessageImpl() { + this.from = new EndpointReferenceImpl("/"); + this.to = new EndpointReferenceImpl("/"); + } + + @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 EndpointReference getTo() { + return to; + } + + public void setTo(EndpointReference to) { + this.to = to; + } + + public Operation getOperation() { + return operation; + } + + public void setOperation(Operation op) { + this.operation = op; + } + + public Map getQoSContext() { + return qosContext; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NoMethodForOperationException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NoMethodForOperationException.java new file mode 100644 index 0000000000..eca2279024 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NoMethodForOperationException.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.invocation; + + +/** + * Thrown when an {@link org.apache.tuscany.sca.core.factory.model.Operation} cannot be mapped to a method on an interface + * @version $Rev: 567617 $ $Date: 2007-08-20 02:29:15 -0700 (Mon, 20 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java new file mode 100644 index 0000000000..e98c6ac9a8 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import java.util.LinkedList; +import java.util.Map; + +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.EndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.osoa.sca.ServiceRuntimeException; + +/** + * Adds non-blocking behavior to an invocation chain + * + * @version $$Rev: 639271 $$ $$Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $$ + */ +public class NonBlockingInterceptor implements Interceptor { + + private static final Message RESPONSE = new ImmutableMessage(); + + 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 { + next.invoke(msg); + } 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 { + + @SuppressWarnings("unchecked") + 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 EndpointReference getTo() { + return null; + } + + public void setFrom(EndpointReference from) { + throw new UnsupportedOperationException(); + } + + public void setTo(EndpointReference 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; + } + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseManager.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseManager.java new file mode 100644 index 0000000000..50b4b59d73 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseManager.java @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.io.IOException; +import java.util.ArrayList; +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.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.invocation.Phase; +import org.osoa.sca.ServiceRuntimeException; + +/** + * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $ + */ +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_SERVICE = "service"; + public static final String STAGE_IMPLEMENTATION = "implementation"; + private final static String[] SYSTEM_REFERENCE_PHASES = + {Phase.REFERENCE, Phase.REFERENCE_INTERFACE, Phase.REFERENCE_POLICY, Phase.REFERENCE_BINDING}; + + private final static String[] SYSTEM_SERVICE_PHASES = + {Phase.SERVICE_BINDING, Phase.SERVICE_POLICY, Phase.SERVICE_INTERFACE, Phase.SERVICE}; + + private final static String[] SYSTEM_IMPLEMENTATION_PHASES = {Phase.IMPLEMENTATION_POLICY, Phase.IMPLEMENTATION}; + + 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; + } + + public String toString() { + return name + phases; + } + } + + // For unit test purpose + PhaseManager(String pattern) { + super(); + this.pattern = pattern; + } + + public PhaseManager() { + } + + 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 getImplementationPhases() { + return getPhases(STAGE_IMPLEMENTATION); + } + + public List getAllPhases() { + if (phases == null) { + phases = new ArrayList(); + phases.addAll(getReferencePhases()); + phases.addAll(getServicePhases()); + phases.addAll(getImplementationPhases()); + } + return phases; + } + + public synchronized Map getStages() { + if (stages != null) { + return stages; + } + init(); + + Set services; + try { + services = ServiceDiscovery.getInstance().getServiceDeclarations(pattern); + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } + + for (ServiceDeclaration d : services) { + if (log.isLoggable(Level.FINE)) { + log.fine(d.getResource() + ": " + 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: " + stage); + } + 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(Phase.REFERENCE_BINDING); + stages.put(referenceStage.getName(), referenceStage); + + 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(Phase.IMPLEMENTATION); + stages.put(implementationStage.getName(), implementationStage); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseSorter.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseSorter.java new file mode 100644 index 0000000000..8e8a89c963 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/PhaseSorter.java @@ -0,0 +1,234 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +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 + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java new file mode 100644 index 0000000000..b7cfb2c4c9 --- /dev/null +++ b/branches/sca-android/core-android/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: 567617 $$ $$Date: 2007-08-20 02:29:15 -0700 (Mon, 20 Aug 2007) $$ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java new file mode 100644 index 0000000000..cd59fdb0aa --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.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.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; + +/** + * Creates proxies that implement Java interfaces and invocation handlers for fronting wires + * + * @version $$Rev: 639271 $$ $$Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $$ + */ + +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(CallableReference 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(CallbackReferenceImpl 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java new file mode 100644 index 0000000000..20ea4ca379 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation; + +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; + +/** + * The extension point to plug in proxy factories + * @version $Rev: 561673 $ $Date: 2007-07-31 23:25:09 -0700 (Tue, 31 Jul 2007) $ + */ +public interface ProxyFactoryExtensionPoint extends ProxyFactory { + /** + * 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); + + /** + * @return the interfaceContractMapper + */ + InterfaceContractMapper getInterfaceContractMapper(); + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java new file mode 100644 index 0000000000..7ca30718b5 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeWireInvoker.java @@ -0,0 +1,245 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.conversation.ConversationState; +import org.apache.tuscany.sca.core.conversation.ExtendedConversation; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +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.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.ConversationEndedException; +import org.osoa.sca.ServiceRuntimeException; + +/** + * @version $Rev: 638875 $ $Date: 2008-03-19 08:32:44 -0700 (Wed, 19 Mar 2008) $ + */ +public class RuntimeWireInvoker { + protected ConversationManager conversationManager; + protected boolean conversational; + protected ExtendedConversation conversation; + protected MessageFactory messageFactory; + protected Object conversationID; + protected Object callbackID; + protected Object callbackObject; + protected RuntimeWire wire; + + public RuntimeWireInvoker(MessageFactory messageFactory, ConversationManager conversationManager, RuntimeWire wire) { + this.messageFactory = messageFactory; + this.wire = wire; + this.conversationManager = conversationManager; + init(wire); + } + + 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(); + } + } + + 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.getSource(); + if (from != null) { + from.mergeEndpoint(epFrom); + } else { + msg.setFrom(epFrom); + } + msg.setTo(wire.getTarget()); + + Invoker headInvoker = chain.getHeadInvoker(); + Operation operation = chain.getTargetOperation(); + msg.setOperation(operation); + + Message msgContext = ThreadMessageContext.getMessageContext(); + Object currentConversationID = msgContext.getFrom().getReferenceParameters().getConversationID(); + + ThreadMessageContext.setMessageContext(msg); + try { + 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 { + conversationPostInvoke(msg); + } catch (TargetDestructionException e) { + throw new ServiceRuntimeException(e); + } finally { + ThreadMessageContext.setMessageContext(msgContext); + } + } + } + + /** + * @param msgContext + */ + 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 + */ + 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 + */ + @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 = 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/TargetInvocationException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/TargetInvocationException.java new file mode 100644 index 0000000000..00bf9c831e --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/TargetInvocationException.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; + +/** + * Raised when an error is encountered during a target invocation + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class TargetInvocationException extends Exception { + + private static final long serialVersionUID = -6553427708442761743L; + + public TargetInvocationException() { + super(); + } + + public TargetInvocationException(String message, Throwable cause) { + super(message, cause); + } + + public TargetInvocationException(String message) { + super(message); + } + + public TargetInvocationException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java new file mode 100644 index 0000000000..d5085289e9 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/ThreadMessageContext.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import org.apache.tuscany.sca.core.assembly.EndpointReferenceImpl; +import org.apache.tuscany.sca.invocation.Message; + +/** + * Class for tunnelling a WorkContext through the invocation of a user class. + * + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + */ +public final class ThreadMessageContext { + + private static final ThreadLocal CONTEXT = new ThreadLocal() { + @Override + protected synchronized Message initialValue() { + Message msg = new MessageImpl(); + msg.setFrom(new EndpointReferenceImpl("/")); + return msg; + } + }; + + private ThreadMessageContext() { + } + + /** + * Set the WorkContext for the current thread. + * The current work context is returned and must be restored after the invocation is complete. + * Typical usage would be: + *
+     *   WorkContext old = PojoWorkContextTunnel.setThreadWorkContext(newContext);
+     *   try {
+     *      ... invoke user code ...
+     *   } finally {
+     *     PojoWorkContextTunnel.setThreadWorkContext(old);
+     *   }
+     * 
+ * @param context + * @return the current work context for the thread; this must be restored after the invocation is made + */ + public static Message setMessageContext(Message context) { + Message old = CONTEXT.get(); + CONTEXT.set(context); + return old; + } + + /** + * Returns the WorkContext for the current thread. + * + * @return the WorkContext for the current thread + */ + public static Message getMessageContext() { + return CONTEXT.get(); + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java new file mode 100644 index 0000000000..d6ce9b4582 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.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.invocation; + +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; + +/** + * Uses a wire to return an object instance + * + * @version $Rev: 596162 $ $Date: 2007-11-18 15:50:50 -0800 (Sun, 18 Nov 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java new file mode 100644 index 0000000000..3e981556dc --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java @@ -0,0 +1,201 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.event.Event; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Implements functionality common to scope contexts. + * + * @version $Rev: 639271 $ $Date: 2008-03-20 05:54:38 -0700 (Thu, 20 Mar 2008) $ + */ +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 + } + + public void onEvent(Event event) { + } + + 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainer.java new file mode 100644 index 0000000000..cad9279e5c --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainer.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A scope context which manages atomic component instances keyed by composite + * + * @version $Rev: 571516 $ $Date: 2007-08-31 09:41:22 -0700 (Fri, 31 Aug 2007) $ + */ +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) { + wrapper = createInstanceWrapper(); + wrapper.start(); + } + 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainerFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainerFactory.java new file mode 100644 index 0000000000..c9693761e8 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/CompositeScopeContainerFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class CompositeScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new CompositeScopeContainer(component); + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainer.java new file mode 100644 index 0000000000..55244932c5 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainer.java @@ -0,0 +1,290 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.conversation.ConversationListener; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.conversation.ExtendedConversation; +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.store.Store; + +/** + * A scope context which manages atomic component instances keyed on ConversationID + * + */ +public class ConversationalScopeContainer extends AbstractScopeContainer implements ConversationListener { + private ConversationManager conversationManager; + private Map instanceLifecycleCollection = + new ConcurrentHashMap(); + + public ConversationalScopeContainer(Store aStore, RuntimeComponent component) { + super(Scope.CONVERSATION, component); + + // Note: aStore is here to preserve the original factory interface. It is not currently used in this + // implementation since we do not support instance persistence. + + // Check System properties to see if timeout values have been specified. All timeout values + // will be specified in seconds. + // + + } + + + protected InstanceWrapper getInstanceWrapper(boolean create, Object contextId) throws TargetResolutionException { + + // we might get a null context if the target service has + // conversational scope but only its callback interface + // is conversational. In this case we need to invent a + // conversation Id here to store the service against + // and populate the thread context + if (contextId == null) { + contextId = UUID.randomUUID().toString(); + Message msgContext = ThreadMessageContext.getMessageContext(); + + if (msgContext != null) { + msgContext.getFrom().getReferenceParameters().setConversationID(contextId); + } + } + + InstanceLifeCycleWrapper anInstanceWrapper = this.instanceLifecycleCollection.get(contextId); + + if (anInstanceWrapper == null && !create) + return null; + + if (anInstanceWrapper == null) { + anInstanceWrapper = new InstanceLifeCycleWrapper(contextId); + this.instanceLifecycleCollection.put(contextId, anInstanceWrapper); + } + + return anInstanceWrapper.getInstanceWrapper(contextId); + + } + + @Override + public InstanceWrapper getWrapper(Object contextId) throws TargetResolutionException { + return getInstanceWrapper(true, contextId); + } + + /** + * This method allows a new context id to be registered alongside an existing one. This happens in + * one case, when a conversation includes a stateful callback. The client component instance + * must be registered against all outgoing conversation ids so that the component instance + * can be found when the callback arrives + * + * @param existingContextId the context id against which the component is already registered + * @param context this should be a conversation object so that the conversation can b stored + * and reset when the component instance is removed + */ + public void addWrapperReference(Object existingContextId, Object contextId) throws TargetResolutionException { + + + // get the instance wrapper via the existing id + InstanceLifeCycleWrapper existingInstanceWrapper = this.instanceLifecycleCollection.get(existingContextId); + InstanceLifeCycleWrapper newInstanceWrapper = this.instanceLifecycleCollection.get(contextId); + + // only add the extra reference once + if (newInstanceWrapper == null) { + // add the id to the list of ids that the wrapper holds. Used for reference + // counting and conversation resetting on destruction. + existingInstanceWrapper.addCallbackConversation(contextId); + + // add the reference to the collection + this.instanceLifecycleCollection.put(contextId, existingInstanceWrapper); + } + } + + public void registerWrapper(InstanceWrapper wrapper, Object contextId) throws TargetResolutionException { + // if a wrapper for a different instance is already registered for this contextId, remove it + InstanceLifeCycleWrapper anInstanceWrapper = this.instanceLifecycleCollection.get(contextId); + if (anInstanceWrapper != null) { + if (anInstanceWrapper.getInstanceWrapper(contextId).getInstance() != wrapper.getInstance()) { + remove(contextId); + } else { + return; + } + } + + anInstanceWrapper = new InstanceLifeCycleWrapper(wrapper, contextId); + this.instanceLifecycleCollection.put(contextId, anInstanceWrapper); + } + + // The remove is invoked when a conversation is explicitly ended. This can occur by using the @EndsConversation or API. + // In this case the instance is immediately removed. A new conversation will be started on the next operation + // associated with this conversationId's service reference. + // + @Override + public void remove(Object contextId) throws TargetDestructionException { + if (contextId != null) { + if (this.instanceLifecycleCollection.containsKey(contextId)) { + InstanceLifeCycleWrapper anInstanceLifeCycleWrapper = this.instanceLifecycleCollection.get(contextId); + this.instanceLifecycleCollection.remove(contextId); + anInstanceLifeCycleWrapper.removeInstanceWrapper(contextId); + } + } + } + + /* + * This is an inner class that keeps track of the lifecycle of a conversation scoped + * implementation instance. + * + */ + + private class InstanceLifeCycleWrapper { + private Object clientConversationId; + private List callbackConversations = new ArrayList(); + + private InstanceLifeCycleWrapper(Object contextId) throws TargetResolutionException { + this.clientConversationId = contextId; + this.createInstance(contextId); + } + + private InstanceLifeCycleWrapper(InstanceWrapper wrapper, Object contextId) throws TargetResolutionException { + this.clientConversationId = contextId; + wrappers.put(contextId, wrapper); + } + + + // Associates a callback conversation with this instance. Each time the scope container + // is asked to remove an object given a ontextId an associated conversation object will + // have its conversationId reset to null. When the list of ids is empty the component instance + // will be removed from the scope container + private void addCallbackConversation(Object conversationID) { + InstanceWrapper ctx = getInstanceWrapper(clientConversationId); + callbackConversations.add(conversationID); + wrappers.put(conversationID, ctx); + } + + // + // Return the backing implementation instance + // + private InstanceWrapper getInstanceWrapper(Object contextId) { + InstanceWrapper ctx = wrappers.get(contextId); + return ctx; + } + + private void removeInstanceWrapper(Object contextId) throws TargetDestructionException { + InstanceWrapper ctx = getInstanceWrapper(contextId); + wrappers.remove(contextId); + + // find out if we are dealing with the original client conversation id + // and reset accordingly + if ( ( clientConversationId != null ) && ( clientConversationId.equals(contextId)) ) { + clientConversationId = null; + } else { + // reset the conversationId in the conversation object if present + // so that and ending callback causes the conversation in the originating + // service reference in the client to be reset + callbackConversations.remove(contextId); + } + + // stop the component if this removes the last reference + if (clientConversationId == null && callbackConversations.isEmpty()) { + ctx.stop(); + } + } + + private void createInstance(Object contextId) throws TargetResolutionException { + InstanceWrapper instanceWrapper = createInstanceWrapper(); + instanceWrapper.start(); + wrappers.put(contextId, instanceWrapper); + } + + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationListener#conversationEnded(org.apache.tuscany.sca.core.conversation.ExtendedConversation) + */ + public void conversationEnded(ExtendedConversation conversation) { + try { + remove(conversation.getConversationID()); + } catch (Exception ex) { + + } + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationListener#conversationExpired(org.apache.tuscany.sca.core.conversation.ExtendedConversation) + */ + public void conversationExpired(ExtendedConversation conversation) { + + Object conversationId = conversation.getConversationID(); + InstanceLifeCycleWrapper ilcw = instanceLifecycleCollection.get(conversationId); + if (ilcw != null) + { + // cycle through all the references to this instance and + // remove them from the underlying wrappers collection and + // from the lifecycle wrappers collection + + for (Object conversationID : ilcw.callbackConversations) { + try{ + ilcw.removeInstanceWrapper(conversationID); + remove(conversationID); + } + catch(TargetDestructionException tde){ + System.out.println("Could not remove conversation id " + conversationID); + } + } + + + if (ilcw.clientConversationId != null) { + try{ + ilcw.removeInstanceWrapper(ilcw.clientConversationId); + remove(ilcw.clientConversationId); + } + catch(TargetDestructionException tde){ + System.out.println("Could not remove conversation id " + ilcw.clientConversationId); + } + } + + } + + } + + /** + * @see org.apache.tuscany.sca.core.conversation.ConversationListener#conversationStarted(org.apache.tuscany.sca.core.conversation.ExtendedConversation) + */ + public void conversationStarted(ExtendedConversation conversation) { + startContext(conversation.getConversationID()); + } + + /** + * @return the conversationManager + */ + public ConversationManager getConversationManager() { + return conversationManager; + } + + /** + * @param conversationManager the conversationManager to set + */ + public void setConversationManager(ConversationManager conversationManager) { + this.conversationManager = conversationManager; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainerFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainerFactory.java new file mode 100644 index 0000000000..487d2874b0 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ConversationalScopeContainerFactory.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; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.store.Store; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class ConversationalScopeContainerFactory implements ScopeContainerFactory { + private Store store; + + public ConversationalScopeContainerFactory(Store store) { + super(); + this.store = store; + } + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new ConversationalScopeContainer(store, component); + } + + public Scope getScope() { + return Scope.CONVERSATION; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainer.java new file mode 100644 index 0000000000..62f1e3fb79 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainer.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.event.HttpSessionEnd; +import org.apache.tuscany.sca.event.Event; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A scope context which manages atomic component instances keyed on HTTP + * session + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class HttpSessionScopeContainer extends AbstractScopeContainer { + + public HttpSessionScopeContainer(RuntimeComponent component) { + super(Scope.SESSION, component); + } + + @Override + public void onEvent(Event event) { + checkInit(); + if (event instanceof HttpSessionEnd) { + //FIXME key is not used + //Object key = ((HttpSessionEnd)event).getSessionID(); + // FIXME: Remove the session id + } + } + + @Override + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + @Override + public synchronized void stop() { + lifecycleState = STOPPED; + } + + protected InstanceWrapper getInstanceWrapper(boolean create) throws TargetResolutionException { +// Object key = workContext.getIdentifier(Scope.SESSION); + // FIXME: Need to fix this + Object key ="http-session-id"; + assert key != null : "HTTP session key not bound in work context"; + InstanceWrapper ctx = wrappers.get(key); + if (ctx == null && !create) { + return null; + } + if (ctx == null) { + ctx = super.createInstanceWrapper(); + ctx.start(); + wrappers.put(key, ctx); + } + return ctx; + } + + @Override + public InstanceWrapper getWrapper(Object contextId) throws TargetResolutionException { + return getInstanceWrapper(true); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainerFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainerFactory.java new file mode 100644 index 0000000000..c42700c9a6 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/HttpSessionScopeContainerFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class HttpSessionScopeContainerFactory implements ScopeContainerFactory { + + public HttpSessionScopeContainerFactory() { + super(); + } + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new HttpSessionScopeContainer(component); + } + + public Scope getScope() { + return Scope.SESSION; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainer.java new file mode 100644 index 0000000000..761430597c --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainer.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.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.event.RequestEnd; +import org.apache.tuscany.sca.event.Event; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A scope context which manages atomic component instances keyed on the current + * request context + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class RequestScopeContainer extends AbstractScopeContainer { + private final Map contexts; + + public RequestScopeContainer(RuntimeComponent component) { + super(Scope.REQUEST, component); + contexts = new ConcurrentHashMap(); + } + + @Override + public void onEvent(Event event) { + checkInit(); + if (event instanceof RequestEnd) { + // shutdownInstances(Thread.currentThread()); + } + } + + @Override + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + @Override + public synchronized void stop() { + contexts.clear(); + // synchronized (destroyQueues) { + // destroyQueues.clear(); + // } + lifecycleState = STOPPED; + } + + protected InstanceWrapper getInstanceWrapper(boolean create) throws TargetResolutionException { + InstanceWrapper ctx = wrappers.get(Thread.currentThread()); + if (ctx == null && !create) { + return null; + } + if (ctx == null) { + ctx = super.createInstanceWrapper(); + ctx.start(); + wrappers.put(Thread.currentThread(), ctx); + } + return ctx; + } + + @Override + public InstanceWrapper getWrapper(Thread contextId) throws TargetResolutionException { + return getInstanceWrapper(true); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainerFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainerFactory.java new file mode 100644 index 0000000000..c2a3172fe2 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/RequestScopeContainerFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class RequestScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new RequestScopeContainer(component); + } + + public Scope getScope() { + return Scope.REQUEST; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java new file mode 100644 index 0000000000..1c72359e58 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/Scope.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.core.scope; + +/** + * The default implementation scopes supported by assemblies. + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class Scope { + public static final Scope STATELESS = new Scope("STATELESS"); + public static final Scope REQUEST = new Scope("REQUEST"); + public static final Scope SESSION = new Scope("SESSION"); + public static final Scope CONVERSATION = new Scope("CONVERSATION"); + public static final Scope COMPOSITE = new Scope("COMPOSITE"); + public static final Scope SYSTEM = new Scope("SYSTEM"); + public static final Scope UNDEFINED = new Scope("UNDEFINED"); + + 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java new file mode 100644 index 0000000000..ea91c5973c --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.event.RuntimeEventListener; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * Manages the lifecycle and visibility of instances associated with a an {@link RuntimeComponent}. + * + * @version $Rev: 572525 $ $Date: 2007-09-03 22:00:52 -0700 (Mon, 03 Sep 2007) $ + * @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 extends RuntimeEventListener { + + /** + * 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java new file mode 100644 index 0000000000..e5f23f9a0a --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public interface ScopeContainerFactory { + ScopeContainer createScopeContainer(RuntimeComponent component); + Scope getScope(); +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java new file mode 100644 index 0000000000..6ec5667cb1 --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $$ $$Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $$ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistryImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistryImpl.java new file mode 100644 index 0000000000..6c25dbd2d4 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistryImpl.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; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * The default implementation of a scope registry + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +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; + } + ScopeContainerFactory factory = scopeCache.get(scope); + ScopeContainer container = factory.createScopeContainer(component); + component.setScopeContainer(container); + return container; + } + return null; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java new file mode 100644 index 0000000000..8708c6e11e --- /dev/null +++ b/branches/sca-android/core-android/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.context.InstanceWrapper; +import org.apache.tuscany.sca.provider.ImplementationProvider; + +/** + * A component implementation can implement this interface to provide scope + * management for the components + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java new file mode 100644 index 0000000000..c533822952 --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainer.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainer.java new file mode 100644 index 0000000000..f785647683 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainer.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.scope; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A scope context which manages stateless atomic component instances in a non-pooled fashion. + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class StatelessScopeContainer extends AbstractScopeContainer { + + public StatelessScopeContainer(RuntimeComponent component) { + super(Scope.STATELESS, component); + } + + @Override + public InstanceWrapper getWrapper(KEY contextId) + throws TargetResolutionException { + 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainerFactory.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainerFactory.java new file mode 100644 index 0000000000..7507248b32 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/StatelessScopeContainerFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class StatelessScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new StatelessScopeContainer(component); + } + + public Scope getScope() { + return Scope.STATELESS; + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java new file mode 100644 index 0000000000..a3c4e7ee1a --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java new file mode 100644 index 0000000000..29f43ed861 --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java new file mode 100644 index 0000000000..b8b1d6bbe3 --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $$ $$Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $$ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java new file mode 100644 index 0000000000..d669711c40 --- /dev/null +++ b/branches/sca-android/core-android/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: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/store/MemoryStore.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/store/MemoryStore.java new file mode 100644 index 0000000000..bed8f14cdc --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/store/MemoryStore.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.store; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.tuscany.sca.core.event.BaseEventPublisher; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.store.DuplicateRecordException; +import org.apache.tuscany.sca.store.RecoveryListener; +import org.apache.tuscany.sca.store.Store; +import org.apache.tuscany.sca.store.StoreExpirationEvent; +import org.apache.tuscany.sca.store.StoreMonitor; +import org.apache.tuscany.sca.store.StoreWriteException; +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Service; + +/** + * Implements a non-durable, non-transactional store using a simple in-memory map + * + * @version $Rev: 538423 $ $Date: 2007-05-15 21:11:06 -0700 (Tue, 15 May 2007) $ + */ +@Service(Store.class) +@EagerInit +public class MemoryStore extends BaseEventPublisher implements Store { + private Map> store; + // TODO integrate with a core threading scheme + private ScheduledExecutorService scheduler; + private long reaperInterval = 300000; + private StoreMonitor monitor; + private long defaultExpirationOffset = 600000; // 10 minutes + + public MemoryStore(StoreMonitor monitor) { + this.monitor = monitor; + this.store = new ConcurrentHashMap>(); + this.scheduler = Executors.newSingleThreadScheduledExecutor(); + } + + /** + * Returns the maximum default expiration offset for records in the store + * + * @return the maximum default expiration offset for records in the store + */ + public long getDefaultExpirationOffset() { + return defaultExpirationOffset; + } + + /** + * Sets the maximum default expiration offset for records in the store + */ + @Property + public void setDefaultExpirationOffset(long defaultExpirationOffset) { + this.defaultExpirationOffset = defaultExpirationOffset; + } + + /** + * Sets the interval for expired entry scanning to be performed + */ + @Property + public void setReaperInterval(long reaperInterval) { + this.reaperInterval = reaperInterval; + } + + public long getReaperInterval() { + return reaperInterval; + } + + @Init + public void init() { + scheduler.scheduleWithFixedDelay(new Reaper(), reaperInterval, reaperInterval, TimeUnit.MILLISECONDS); + monitor.start("In-memory store started"); + } + + @Destroy + public void destroy() { + scheduler.shutdown(); + monitor.stop("In-memory store stopped"); + } + + public void insertRecord(RuntimeComponent owner, String id, Object object, long expiration) throws StoreWriteException { + Map map = store.get(owner); + if (map == null) { + map = new ConcurrentHashMap(); + store.put(owner, map); + } + if (map.containsKey(id)) { + throw new DuplicateRecordException("Duplicate record: " + owner.getURI() +" : " + id); + } + map.put(id, new Record(object, expiration)); + } + + public void updateRecord(RuntimeComponent owner, String id, Object object, long expiration) throws StoreWriteException { + Map map = store.get(owner); + if (map == null) { + throw new StoreWriteException("Record not found: " + owner.getURI() +" : " + id); + } + Record record = map.get(id); + if (record == null) { + throw new StoreWriteException("Record not found: " + owner.getURI() +" : " + id); + } + record.data = object; + } + + public Object readRecord(RuntimeComponent owner, String id) { + Map map = store.get(owner); + if (map == null) { + return null; + } + Record record = map.get(id); + if (record != null) { + return record.data; + } + return null; + } + + public void removeRecords() { + store.clear(); + } + + public void removeRecord(RuntimeComponent owner, String id) throws StoreWriteException { + Map map = store.get(owner); + if (map == null) { + throw new StoreWriteException("Owner not found: " + owner.getURI() +" : " + id); + } + if (map.remove(id) == null) { + throw new StoreWriteException("Owner not found: " + owner.getURI() +" : " + id); + } + } + + public void recover(RecoveryListener listener) { + throw new UnsupportedOperationException(); + } + + private class Record { + private Object data; + private long expiration = NEVER; + + public Record(Object data, long expiration) { + this.data = data; + this.expiration = expiration; + } + + public Object getData() { + return data; + } + + public long getExpiration() { + return expiration; + } + } + + private class Reaper implements Runnable { + + public void run() { + long now = System.currentTimeMillis(); + for (Map.Entry> entries : store.entrySet()) { + for (Map.Entry entry : entries.getValue().entrySet()) { + final long expiration = entry.getValue().expiration; + if (expiration != NEVER && now >= expiration) { + RuntimeComponent owner = entries.getKey(); + Object instance = entry.getValue().getData(); + // notify listeners of the expiration + StoreExpirationEvent event = new StoreExpirationEvent(this, owner, instance); + publish(event); + entries.getValue().remove(entry.getKey()); + } + } + } + } + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237Work.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237Work.java new file mode 100644 index 0000000000..982b2a0492 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237Work.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.work; + +/* + * JCA work wrapper. + */ +public class Jsr237Work implements commonj.work.Work { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public Jsr237Work(T work) { + this.work = work; + } + + /* + * Returns the completed work. + */ + public T getWork() { + return work; + } + + /* + * Release the work. + */ + public void release() { + } + + /* + * Work attributes are not daemon. + */ + public boolean isDaemon() { + return false; + } + + /* + * Runs the work. + */ + public void run() { + work.run(); + } +} \ No newline at end of file diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237WorkScheduler.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237WorkScheduler.java new file mode 100644 index 0000000000..ec47d8ac07 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/Jsr237WorkScheduler.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work; + +/*import javax.naming.InitialContext; +import javax.naming.NamingException;*/ + +import org.apache.tuscany.sca.work.NotificationListener; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.apache.tuscany.sca.work.WorkSchedulerException; + +import commonj.work.WorkEvent; +import commonj.work.WorkListener; +import commonj.work.WorkManager; + +/** + * 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.

+ */ +public class Jsr237WorkScheduler implements WorkScheduler { + + /** + * Underlying JSR-237 work manager + */ + private WorkManager jsr237WorkManager; + + /** + * Initializes the JSR 237 work manager. + * + * @param jsr237WorkManager JSR 237 work manager. + */ + public Jsr237WorkScheduler() { + + /* + try { + InitialContext ctx = new InitialContext(); + jsr237WorkManager = (WorkManager) ctx.lookup("java:comp/env/wm/TuscanyWorkManager"); + } catch (NamingException e) { + // ignore + }*/ + + if (jsr237WorkManager == null) { + jsr237WorkManager = new ThreadPoolWorkManager(10); + } + } + + /** + * 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"); + } + + Jsr237Work jsr237Work = new Jsr237Work(work); + try { + if (listener == null) { + jsr237WorkManager.schedule(jsr237Work); + } else { + Jsr237WorkListener jsr237WorkListener = new Jsr237WorkListener(listener, work); + jsr237WorkManager.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 destroy() { + if (jsr237WorkManager instanceof ThreadPoolWorkManager) { + ((ThreadPoolWorkManager)jsr237WorkManager).destroy(); + } + } + + /* + * 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/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/ThreadPoolWorkManager.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/ThreadPoolWorkManager.java new file mode 100644 index 0000000000..5731ac5697 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/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; + +//import java.rmi.server.UID; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; + +import org.osoa.sca.annotations.Destroy; + +import commonj.work.Work; +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkItem; +import commonj.work.WorkListener; +import commonj.work.WorkManager; + +/** + * A thread-pool based implementation for the JSR-237 work manager. + *

+ *

+ * This implementation supports only local work. + *

+ * TODO Elaborate the implementation.

+ */ +public class ThreadPoolWorkManager implements WorkManager { + + // 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. + */ + public ThreadPoolWorkManager(int threadPoolSize) { + + // Creates a new Executor, use a custom ThreadFactory that + // creates daemon threads. + executor = Executors.newFixedThreadPool(threadPoolSize, new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setDaemon(true); + return thread; + } + }); + } + + /** + * 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 { + + WorkItemImpl workItem = new WorkItemImpl(null/*new UID().toString()*/, work); + if (workListener != null) { + workItems.put(workItem, workListener); + } + workAccepted(workItem, work); + if (scheduleWork(work, workItem)) { + return workItem; + } else { + workItem.setStatus(WorkEvent.WORK_REJECTED); + if (workListener != null) { + workListener.workRejected(new WorkEventImpl(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 WorkItemImpl workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_ACCEPTED); + WorkEvent event = new WorkEventImpl(workItem); + listener.workAccepted(event); + } + } + + /* + * Method to indicate a work start. + */ + private void workStarted(final WorkItemImpl workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_STARTED); + WorkEvent event = new WorkEventImpl(workItem); + listener.workStarted(event); + } + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final WorkItemImpl workItem, final Work work) { + workCompleted(workItem, work, null); + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final WorkItemImpl workItem, final Work work, final WorkException exception) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_COMPLETED); + workItem.setResult(work); + workItem.setException(exception); + WorkEvent event = new WorkEventImpl(workItem); + listener.workCompleted(event); + workItems.remove(workItem); + } + } + + /* + * Schedules the work using the ThreadPool. + */ + private boolean scheduleWork(final Work work, final WorkItemImpl 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 WorkItemImpl workItem; + + // The original work. + private Work decoratedWork; + + /* + * Initializes the work item and underlying work. + */ + private DecoratingWork(final WorkItemImpl workItem, final Work decoratedWork) { + this.workItem = workItem; + this.decoratedWork = decoratedWork; + } + + /* + * Overrides the run method. + */ + public void run() { + workStarted(workItem, decoratedWork); + try { + decoratedWork.run(); + workCompleted(workItem, decoratedWork); + } catch (Throwable th) { + workCompleted(workItem, decoratedWork, new WorkException(th.getMessage(), th)); + } + } + + } + + @Destroy + public void destroy() { + executor.shutdown(); + } + +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkEventImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkEventImpl.java new file mode 100644 index 0000000000..761f682c75 --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkEventImpl.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.work; + + +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkItem; + +/** + * Default immutable implementation of the WorkEvent class. + */ +class WorkEventImpl implements WorkEvent { + + // Work item for this event + private WorkItem workItem; + + // Exception if something has gone wrong + private WorkException exception; + + /** + * Instantiates the event. + * + * @param workItem Work item for this event. + */ + public WorkEventImpl(final WorkItemImpl workItem) { + this.workItem = workItem; + this.exception = workItem.getException(); + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work type. + */ + public int getType() { + return workItem.getStatus(); + } + + /** + * Returns the work item associated with this work type. + * + * @return Work item. + */ + public WorkItem getWorkItem() { + return workItem; + } + + /** + * Returns the exception if the work completed with an exception. + * + * @return Work exception. + */ + public WorkException getException() { + return exception; + } +} diff --git a/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkItemImpl.java b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkItemImpl.java new file mode 100644 index 0000000000..afa496435f --- /dev/null +++ b/branches/sca-android/core-android/src/main/java/org/apache/tuscany/sca/core/work/WorkItemImpl.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work; + +import commonj.work.Work; +import commonj.work.WorkException; +import commonj.work.WorkItem; + +/** + * An identity based immutable implementation of the WorkItem + * interface. + * + */ +class WorkItemImpl implements WorkItem { + + // Id scoped for the VM + private String id; + + // Status + private int status = -1; + + // Result + private Work result; + + // Original work + private Work originalWork; + + // Exception + private WorkException exception; + + /** + * Instantiates an id for this item. + * + * @param id of this work event. + */ + protected WorkItemImpl(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 WorkException getException() { + return exception; + } + + /** + * Sets the exception. + * + * @param exception Exception. + */ + protected void setException(final WorkException exception) { + this.exception = exception; + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work status. + */ + public int getStatus() { + return status; + } + + /** + * Sets the status. + * + * @param status Status. + */ + protected void setStatus(final int status) { + this.status = status; + } + + /** + * @see Object#hashCode() + */ + @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() == WorkItemImpl.class) && ((WorkItemImpl) 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() != WorkItemImpl.class) { + throw new ClassCastException(o.getClass().getName()); + } else { + return ((WorkItemImpl) o).getId().compareTo(getId()); + } + } +} diff --git a/branches/sca-android/core-android/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler b/branches/sca-android/core-android/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler new file mode 100644 index 0000000000..56e99be0f2 --- /dev/null +++ b/branches/sca-android/core-android/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler @@ -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.work.Jsr237WorkScheduler diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistryTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistryTestCase.java new file mode 100644 index 0000000000..b3d1d42ed3 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistryTestCase.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core; + +import junit.framework.TestCase; + +public class DefaultExtensionPointRegistryTestCase extends TestCase { + private ExtensionPointRegistry registry; + + @Override + protected void setUp() throws Exception { + super.setUp(); + registry = new DefaultExtensionPointRegistry(); + } + + public void testRegistry() { + MyRegistry service = new MyREgistryImpl(); + registry.addExtensionPoint(service); + assertSame(service, registry.getExtensionPoint(MyRegistry.class)); + registry.removeExtensionPoint(service); + assertNull(registry.getExtensionPoint(MyRegistry.class)); + } + + public static interface MyRegistry { + void doSomething(); + } + + private static class MyREgistryImpl implements MyRegistry { + + public void doSomething() { + } + + } + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/BaseEventPublisherTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/BaseEventPublisherTestCase.java new file mode 100644 index 0000000000..d4cc0e64d8 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/BaseEventPublisherTestCase.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.event; + + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.event.Event; +import org.apache.tuscany.sca.event.EventFilter; +import org.apache.tuscany.sca.event.EventPublisher; +import org.apache.tuscany.sca.event.RuntimeEventListener; +import org.apache.tuscany.sca.event.TrueFilter; +import org.easymock.EasyMock; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class BaseEventPublisherTestCase extends TestCase { + EventPublisher publisher; + + public void testFireListener() { + Event event = new TestEvent(); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + listener.onEvent(EasyMock.same(event)); + EasyMock.expectLastCall(); + EasyMock.replay(listener); + publisher.addListener(listener); + publisher.publish(event); + EasyMock.verify(listener); + } + + public void testRemoveListener() { + Event event = new TestEvent(); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + EasyMock.replay(listener); + publisher.addListener(listener); + publisher.removeListener(listener); + publisher.publish(event); + EasyMock.verify(listener); + } + + public void testFalseFilterListener() { + Event event = new TestEvent(); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + EasyMock.replay(listener); + publisher.addListener(new FalseFilter(), listener); + publisher.publish(event); + EasyMock.verify(listener); + } + + public void testTrueFilterListener() { + Event event = new TestEvent(); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + listener.onEvent(EasyMock.same(event)); + EasyMock.expectLastCall(); + EasyMock.replay(listener); + publisher.addListener(new TrueFilter(), listener); + publisher.publish(event); + EasyMock.verify(listener); + } + + @Override + protected void setUp() throws Exception { + publisher = new BaseEventPublisher() { + }; + } + + private class TestEvent implements Event { + public Object getSource() { + return null; + } + } + + private class FalseFilter implements EventFilter { + + public boolean match(Event event) { + return false; + } + } + + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/EventTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/EventTestCase.java new file mode 100644 index 0000000000..13f5c14c77 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/event/EventTestCase.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.event; + +import java.net.URI; + +import junit.framework.TestCase; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class EventTestCase extends TestCase { + private URI uri = URI.create("foo"); + + public void testCompositeStart() { + ComponentStart event = new ComponentStart(this, uri); + assertEquals(uri, event.getComponentURI()); + } + + public void testCompositeStop() { + ComponentStop event = new ComponentStop(this, uri); + assertEquals(uri, event.getComponentURI()); + } + + public void testHttpSessionStart() { + Object id = new Object(); + HttpSessionStart event = new HttpSessionStart(this, id); + assertEquals(this, event.getSource()); + assertEquals(id, event.getSessionID()); + } + + public void testHttpSessionEnd() { + Object id = new Object(); + HttpSessionEnd event = new HttpSessionEnd(this, id); + assertEquals(this, event.getSource()); + assertEquals(id, event.getSessionID()); + } + + public void testRequestStart() { + RequestStart event = new RequestStart(this); + assertEquals(this, event.getSource()); + } + + public void testReequestEnd() { + RequestEnd event = new RequestEnd(this); + assertEquals(this, event.getSource()); + } + + + @Override + protected void setUp() throws Exception { + } +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseManagerTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseManagerTestCase.java new file mode 100644 index 0000000000..b8a9d5a591 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseManagerTestCase.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.invocation; + +import java.util.List; + +import junit.framework.Assert; + +import org.junit.Test; + +/** + * @version $Rev: 632098 $ $Date: 2008-02-28 11:37:57 -0800 (Thu, 28 Feb 2008) $ + */ +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/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseSorterTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseSorterTestCase.java new file mode 100644 index 0000000000..a309ac4b15 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/invocation/PhaseSorterTestCase.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 java.util.Arrays; +import java.util.List; + +import junit.framework.TestCase; + +public class PhaseSorterTestCase extends TestCase { + private PhaseSorter graph; + + @Override + protected void setUp() throws Exception { + super.setUp(); + graph = new PhaseSorter(); + } + + 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()); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainerTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainerTestCase.java new file mode 100644 index 0000000000..5601d18746 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainerTestCase.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import java.net.URI; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public abstract class AbstractScopeContainerTestCase extends TestCase { + protected IMocksControl control; + protected ScopeContainer scopeContainer; + protected URI groupId; + protected KEY contextId; + protected RuntimeComponent component; + protected ScopedImplementation implementation; + protected InstanceWrapper wrapper; + + @SuppressWarnings("unchecked") + @Override + protected void setUp() throws Exception { + super.setUp(); + control = EasyMock.createStrictControl(); + component = control.createMock(RuntimeComponent.class); + wrapper = control.createMock(InstanceWrapper.class); + implementation = control.createMock(ScopedImplementation.class); + EasyMock.expect(component.getImplementation()).andReturn(implementation).anyTimes(); + } + + protected void preRegisterComponent() throws Exception { + scopeContainer.start(); + EasyMock.expect(implementation.isEagerInit()).andStubReturn(false); + } + + protected void expectCreateWrapper() throws Exception { + EasyMock.expect(implementation.createInstanceWrapper()).andReturn(wrapper); + wrapper.start(); + } + + protected static interface ScopedImplementation extends ScopedImplementationProvider, Implementation { + + } + + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/store/MemoryStoreTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/store/MemoryStoreTestCase.java new file mode 100644 index 0000000000..3725ce74b0 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/store/MemoryStoreTestCase.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.store; + +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.event.RuntimeEventListener; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.store.DuplicateRecordException; +import org.apache.tuscany.sca.store.Store; +import org.apache.tuscany.sca.store.StoreExpirationEvent; +import org.apache.tuscany.sca.store.StoreMonitor; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class MemoryStoreTestCase extends TestCase { + private StoreMonitor monitor; + + public void testEviction() throws Exception { + MemoryStore store = new MemoryStore(monitor); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createNiceMock(RuntimeComponent.class); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + store.insertRecord(component, id, value, 1); + Thread.sleep(200); + assertNull(store.readRecord(component, id)); + store.destroy(); + } + + public void testNotifyOnEviction() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + listener.onEvent(EasyMock.isA(StoreExpirationEvent.class)); + EasyMock.expectLastCall().andStubAnswer(new IAnswer() { + public Object answer() throws Throwable { + latch.countDown(); + return null; + } + }); + EasyMock.replay(listener); + MemoryStore store = new MemoryStore(monitor); + store.addListener(listener); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createNiceMock(RuntimeComponent.class); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + store.insertRecord(component, id, value, 1); + if (!latch.await(1000, TimeUnit.MILLISECONDS)) { + // failed to notify listener + fail(); + } + EasyMock.verify(listener); + } + + public void testNoEviction() throws Exception { + MemoryStore store = new MemoryStore(monitor); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createNiceMock(RuntimeComponent.class); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + store.insertRecord(component, id, value, Store.NEVER); + Thread.sleep(100); + assertNotNull(store.readRecord(component, id)); + store.destroy(); + } + + public void testInsertRecord() throws Exception { + MemoryStore store = new MemoryStore(monitor); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createNiceMock(RuntimeComponent.class); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + store.insertRecord(component, id, value, Store.NEVER); + store.destroy(); + } + + public void testInsertAlreadyExists() throws Exception { + MemoryStore store = new MemoryStore(monitor); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createMock(RuntimeComponent.class); + EasyMock.expect(component.getURI()).andReturn("component"); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + store.insertRecord(component, id, value, Store.NEVER); + try { + store.insertRecord(component, id, value, Store.NEVER); + fail(); + } catch (DuplicateRecordException e) { + //expected + } + store.destroy(); + } + + public void testUpdateRecord() throws Exception { + MemoryStore store = new MemoryStore(monitor); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createNiceMock(RuntimeComponent.class); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + Object newValue = new Object(); + + store.insertRecord(component, id, value, Store.NEVER); + store.updateRecord(component, id, newValue, 1L); + assertEquals(newValue, store.readRecord(component, id)); + store.destroy(); + } + + public void testDeleteRecord() throws Exception { + MemoryStore store = new MemoryStore(monitor); + store.setReaperInterval(10); + store.init(); + RuntimeComponent component = EasyMock.createNiceMock(RuntimeComponent.class); + EasyMock.replay(component); + String id = UUID.randomUUID().toString(); + Object value = new Object(); + + store.insertRecord(component, id, value, Store.NEVER); + store.removeRecord(component, id); + assertNull(store.readRecord(component, id)); + store.destroy(); + } + + @Override + protected void setUp() throws Exception { + monitor = EasyMock.createNiceMock(StoreMonitor.class); + EasyMock.replay(monitor); + } + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/CallbackInterfaceInterceptorTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/CallbackInterfaceInterceptorTestCase.java new file mode 100644 index 0000000000..424f12800f --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/CallbackInterfaceInterceptorTestCase.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.wire; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.assembly.EndpointReferenceImpl; +import org.apache.tuscany.sca.core.invocation.CallbackInterfaceInterceptor; +import org.apache.tuscany.sca.core.invocation.MessageFactoryImpl; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Message; +import org.easymock.EasyMock; +import org.osoa.sca.NoRegisteredCallbackException; + +/** + * @version $Rev: 608822 $ $Date: 2008-01-04 04:59:56 -0800 (Fri, 04 Jan 2008) $ + */ +public class CallbackInterfaceInterceptorTestCase extends TestCase { + + public void testHasCallbackObject() { + CallbackInterfaceInterceptor interceptor = new CallbackInterfaceInterceptor(); + Interceptor next = EasyMock.createMock(Interceptor.class); + EasyMock.expect(next.invoke(EasyMock.isA(Message.class))).andReturn(null); + EasyMock.replay(next); + interceptor.setNext(next); + Message msg = new MessageFactoryImpl().createMessage(); + msg.setFrom(new EndpointReferenceImpl("uri")); + msg.getFrom().getReferenceParameters().setCallbackObjectID("ABC"); + interceptor.invoke(msg); + EasyMock.verify(next); + } + + public void testNoCallbackObject() { + CallbackInterfaceInterceptor interceptor = new CallbackInterfaceInterceptor(); + Message msg = new MessageFactoryImpl().createMessage(); + msg.setFrom(new EndpointReferenceImpl("uri")); + msg.getFrom().getReferenceParameters().setCallbackObjectID(null); + try { + interceptor.invoke(msg); + fail(); + } catch (NoRegisteredCallbackException e) { + // expected + } + } + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/InvocationChainImplTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/InvocationChainImplTestCase.java new file mode 100644 index 0000000000..120fe861c8 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/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.wire; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.invocation.InvocationChainImpl; +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; + +/** + * @version $Rev: 632064 $ $Date: 2008-02-28 09:18:51 -0800 (Thu, 28 Feb 2008) $ + */ +public class InvocationChainImplTestCase extends TestCase { + + public void testInsertAtEnd() throws Exception { + Operation op = newOperation("foo"); + InvocationChain chain = new InvocationChainImpl(op, op, true); + 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()); + assertEquals(inter2, chain.getTailInvoker()); + + } + + public void testAddByPhase() throws Exception { + Operation op = newOperation("foo"); + InvocationChain chain = new InvocationChainImpl(op, op, false); + 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()); + assertEquals(inter4, chain.getTailInvoker()); + } + + 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/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/NonBlockingInterceptorTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/NonBlockingInterceptorTestCase.java new file mode 100644 index 0000000000..971d9493c8 --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/core/wire/NonBlockingInterceptorTestCase.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.wire; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.getCurrentArguments; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + +/** + * @version $Rev: 576235 $ $Date: 2007-09-16 19:07:54 -0700 (Sun, 16 Sep 2007) $ + */ +public class NonBlockingInterceptorTestCase extends TestCase { + + public void testInvoke() throws Exception { + WorkScheduler scheduler = createMock(WorkScheduler.class); + scheduler.scheduleWork(isA(Runnable.class)); + expectLastCall().andStubAnswer(new IAnswer() { + public Object answer() throws Throwable { + Runnable runnable = (Runnable) getCurrentArguments()[0]; + runnable.run(); + return null; + } + }); + replay(scheduler); + Message context = createMock(Message.class); + //String convID = "convID"; + //TODO port to the new way of dealing with conversation IDs later + //EasyMock.expect(context.getConversationID()).andReturn(convID); + EasyMock.replay(context); + ThreadMessageContext.setMessageContext(context); + Message msg = createMock(Message.class); + //TODO port to the new way of dealing with conversation IDs later + //msg.setConversationID(convID); + Interceptor next = EasyMock.createMock(Interceptor.class); + EasyMock.expect(next.invoke(EasyMock.eq(msg))).andReturn(msg); + EasyMock.replay(next); + EasyMock.replay(msg); + Interceptor interceptor = new NonBlockingInterceptor(scheduler, next); + interceptor.invoke(msg); + verify(context); + verify(next); + verify(msg); + } + +} diff --git a/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java new file mode 100644 index 0000000000..504313921c --- /dev/null +++ b/branches/sca-android/core-android/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.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.scope; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.scope.Scope; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class ScopeTestCase extends TestCase { + + public void testEquals() throws Exception { + Scope scope = new Scope("COMPOSITE"); + assertTrue(scope.equals(Scope.COMPOSITE)); + } + + public void testEqualsNew() throws Exception { + Scope foo = new Scope("foo"); + Scope foo2 = new Scope("FOO"); + assertTrue(foo.equals(foo2)); + } + + public void testNotEquals() throws Exception { + Scope foo = new Scope("BAR"); + Scope foo2 = new Scope("FOO"); + assertFalse(foo.equals(foo2)); + } + + 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/branches/sca-android/core-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest b/branches/sca-android/core-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest new file mode 100644 index 0000000000..1f2218aba8 --- /dev/null +++ b/branches/sca-android/core-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest @@ -0,0 +1,5 @@ +name=implementation.last, stage=implementation, after=* +name=reference.first, stage=reference, before=* +name=reference.transaction, stage=reference, after=reference.interface +name=service.transaction, stage=service, after=service.binding, before=component.service +name=implementation.transaction, stage=implementation, before=implementation.policy \ No newline at end of file diff --git a/branches/sca-android/core-databinding/.classpath b/branches/sca-android/core-databinding/.classpath new file mode 100644 index 0000000000..57c14f73d6 --- /dev/null +++ b/branches/sca-android/core-databinding/.classpath @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/core-databinding/.project b/branches/sca-android/core-databinding/.project new file mode 100644 index 0000000000..1ff4bcab93 --- /dev/null +++ b/branches/sca-android/core-databinding/.project @@ -0,0 +1,31 @@ + + tuscany-core-databinding + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-assembly-xml + tuscany-contribution + tuscany-contribution-java + tuscany-contribution-namespace + tuscany-core + tuscany-core-spi + tuscany-databinding + tuscany-databinding-jaxb + tuscany-definitions + tuscany-extensibility + tuscany-interface + tuscany-interface-java + tuscany-interface-java-jaxws + tuscany-interface-java-xml + tuscany-policy + tuscany-sca-api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/core-databinding/DISCLAIMER b/branches/sca-android/core-databinding/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/core-databinding/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/core-databinding/LICENSE b/branches/sca-android/core-databinding/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/core-databinding/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/branches/sca-android/core-databinding/NOTICE b/branches/sca-android/core-databinding/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/core-databinding/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/core-databinding/pom.xml b/branches/sca-android/core-databinding/pom.xml new file mode 100644 index 0000000000..2d0facb551 --- /dev/null +++ b/branches/sca-android/core-databinding/pom.xml @@ -0,0 +1,76 @@ + + + + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + 4.0.0 + org.apache.tuscany.sca + tuscany-core-databinding + jar + Apache Tuscany SCA Core/DataBinding Integration + + + + org.apache.tuscany.sca + tuscany-databinding + ${project.version} + compile + + + + org.apache.tuscany.sca + tuscany-databinding-jaxb + ${project.version} + compile + + + + org.apache.tuscany.sca + tuscany-core-spi + ${project.version} + compile + + + + org.apache.tuscany.sca + tuscany-interface-java-xml + ${project.version} + compile + + + + org.apache.tuscany.sca + tuscany-interface-java-jaxws + ${project.version} + compile + + + + org.codehaus.woodstox + wstx-asl + runtime + 3.2.1 + + + diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java new file mode 100644 index 0000000000..d936de20ab --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.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.databinding.module; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.core.databinding.processor.DataBindingJavaInterfaceProcessor; +import org.apache.tuscany.sca.core.databinding.transformers.Array2ArrayTransformer; +import org.apache.tuscany.sca.core.databinding.transformers.Exception2ExceptionTransformer; +import org.apache.tuscany.sca.core.databinding.transformers.Input2InputTransformer; +import org.apache.tuscany.sca.core.databinding.transformers.Output2OutputTransformer; +import org.apache.tuscany.sca.core.databinding.wire.DataBindingRuntimeWireProcessor; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultTransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.Group2GroupTransformer; +import org.apache.tuscany.sca.databinding.impl.MediatorImpl; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSFaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSJavaInterfaceProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; + +/** + * @version $Rev: 629687 $ $Date: 2008-02-20 20:11:14 -0800 (Wed, 20 Feb 2008) $ + */ +public class DataBindingModuleActivator implements ModuleActivator { + + public void start(ExtensionPointRegistry registry) { + DataBindingExtensionPoint dataBindings = registry.getExtensionPoint(DataBindingExtensionPoint.class); + + TransformerExtensionPoint transformers = new DefaultTransformerExtensionPoint();//registry.getExtensionPoint(TransformerExtensionPoint.class); + + FaultExceptionMapper faultExceptionMapper = new JAXWSFaultExceptionMapper(dataBindings); + registry.addExtensionPoint(faultExceptionMapper); + + MediatorImpl mediator = new MediatorImpl(dataBindings, transformers); + Input2InputTransformer input2InputTransformer = new Input2InputTransformer(); + input2InputTransformer.setMediator(mediator); + transformers.addTransformer(input2InputTransformer, true); + + Output2OutputTransformer output2OutputTransformer = new Output2OutputTransformer(); + output2OutputTransformer.setMediator(mediator); + transformers.addTransformer(output2OutputTransformer, true); + + Exception2ExceptionTransformer exception2ExceptionTransformer = new Exception2ExceptionTransformer(mediator, faultExceptionMapper); + transformers.addTransformer(exception2ExceptionTransformer, false); + + Array2ArrayTransformer array2ArrayTransformer = new Array2ArrayTransformer(); + array2ArrayTransformer.setMediator(mediator); + transformers.addTransformer(array2ArrayTransformer, true); + + Group2GroupTransformer group2GroupTransformer = new Group2GroupTransformer(); + group2GroupTransformer.setMediator(mediator); + transformers.addTransformer(group2GroupTransformer, true); + + ModelFactoryExtensionPoint modelFactories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + JavaInterfaceFactory javaFactory = modelFactories.getFactory(JavaInterfaceFactory.class); + + // [rfeng] The JAX-WS processor should come before the Databinding processor to make sure @WebService + // is honored as Remoteable + javaFactory.addInterfaceVisitor(new JAXWSJavaInterfaceProcessor(faultExceptionMapper)); + + javaFactory.addInterfaceVisitor(new DataBindingJavaInterfaceProcessor(dataBindings)); + + RuntimeWireProcessorExtensionPoint wireProcessorExtensionPoint = registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class); + if (wireProcessorExtensionPoint != null) { + wireProcessorExtensionPoint.addWireProcessor(new DataBindingRuntimeWireProcessor(mediator, dataBindings, faultExceptionMapper)); + } + + } + + public void stop(ExtensionPointRegistry registry) { + } +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java new file mode 100644 index 0000000000..05d1d71558 --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.databinding.processor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.annotation.DataBinding; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; + +/** + * The databinding annotation processor for java interfaces + * + * @version $Rev: 639350 $ $Date: 2008-03-20 08:43:46 -0800 (Thu, 20 Mar 2008) $ + */ +public class DataBindingJavaInterfaceProcessor implements JavaInterfaceVisitor { + private DataBindingExtensionPoint dataBindingRegistry; + + public DataBindingJavaInterfaceProcessor(DataBindingExtensionPoint dataBindingRegistry) { + super(); + this.dataBindingRegistry = dataBindingRegistry; + } + + public void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException { + if (!javaInterface.isRemotable()) { + return; + } + List operations = javaInterface.getOperations(); + processInterface(javaInterface, operations); + } + + private void processInterface(JavaInterface javaInterface, List operations) { + Class clazz = javaInterface.getJavaClass(); + DataBinding dataBinding = clazz.getAnnotation(DataBinding.class); + String dataBindingId = null; + boolean wrapperStyle = false; + if (dataBinding != null) { + dataBindingId = dataBinding.value(); + wrapperStyle = dataBinding.wrapped(); + } + + Map opMap = new HashMap(); + for (Operation op : javaInterface.getOperations()) { + opMap.put(op.getName(), op); + // In the case of @WebMethod, the method name can be different from the operation name + if (op instanceof JavaOperation) { + opMap.put(((JavaOperation)op).getJavaMethod().getName(), op); + } + if (dataBindingId != null) { + op.setDataBinding(dataBindingId); + op.setWrapperStyle(wrapperStyle); + } + } + for (Method method : clazz.getMethods()) { + if (method.getDeclaringClass() == Object.class) { + continue; + } + Operation operation = opMap.get(method.getName()); + DataBinding methodDataBinding = clazz.getAnnotation(DataBinding.class); + if (methodDataBinding == null) { + methodDataBinding = dataBinding; + } + dataBindingId = null; + wrapperStyle = false; + if (dataBinding != null) { + dataBindingId = dataBinding.value(); + wrapperStyle = dataBinding.wrapped(); + operation.setDataBinding(dataBindingId); + operation.setWrapperStyle(wrapperStyle); + } + + // FIXME: We need a better way to identify simple java types + int i = 0; + for (org.apache.tuscany.sca.interfacedef.DataType d : operation.getInputType().getLogical()) { + if (d.getDataBinding() == null) { + d.setDataBinding(dataBindingId); + } + for (Annotation a : method.getParameterAnnotations()[i]) { + if (a.annotationType() == org.apache.tuscany.sca.databinding.annotation.DataType.class) { + String value = ((org.apache.tuscany.sca.databinding.annotation.DataType)a).value(); + d.setDataBinding(value); + } + } + dataBindingRegistry.introspectType(d, method.getParameterAnnotations()[i]); + i++; + } + if (operation.getOutputType() != null) { + DataType d = operation.getOutputType(); + if (d.getDataBinding() == null) { + d.setDataBinding(dataBindingId); + } + org.apache.tuscany.sca.databinding.annotation.DataType dt = + method.getAnnotation(org.apache.tuscany.sca.databinding.annotation.DataType.class); + if (dt != null) { + d.setDataBinding(dt.value()); + } + dataBindingRegistry.introspectType(d, method.getAnnotations()); + } + for (org.apache.tuscany.sca.interfacedef.DataType d : operation.getFaultTypes()) { + if (d.getDataBinding() == null) { + d.setDataBinding(dataBindingId); + } + // TODO: Handle exceptions + dataBindingRegistry.introspectType(d, method.getAnnotations(), true); + } + + // JIRA: TUSCANY-842 + if (operation.getDataBinding() == null) { + assignOperationDataBinding(operation); + } + + // FIXME: Do we want to heuristically check the wrapper style? + // introspectWrapperStyle(operation); + } + } + + /* + * Assigns an operation DB if one of the input types, output type, fault types has a non-default DB. + * However, if two of the input types, output type, fault types have two different non-default DBs + * ( e.g. SDO and JAXB), then we do nothing to the operation DB. + * + * The method logic assumes the JavaBeans DataBinding is the default + */ + private void assignOperationDataBinding(Operation operation) { + + String nonDefaultDataBindingName = null; + + // Can't use DataType since operation.getInputType() returns: DataType> + List opDataTypes = new LinkedList(); + + opDataTypes.addAll(operation.getInputType().getLogical()); + opDataTypes.add(operation.getOutputType()); + opDataTypes.addAll(operation.getFaultTypes()); + + for (DataType d : opDataTypes) { + if (d != null) { + String dataBinding = d.getDataBinding(); + // Assumes JavaBeans DB is default + if (dataBinding != null && !dataBinding.equals(JavaBeansDataBinding.NAME) + && !dataBinding.equals(SimpleJavaDataBinding.NAME)) { + if (nonDefaultDataBindingName != null) { + if (!nonDefaultDataBindingName.equals(dataBinding)) { + // We've seen two different non-default DBs, e.g. SDO and JAXB + // so unset the string and break out of the loop + nonDefaultDataBindingName = null; + break; + } else { + continue; + } + } else { + nonDefaultDataBindingName = dataBinding; + } + } + } + } + + // We have a DB worthy of promoting to operation level. + if (nonDefaultDataBindingName != null) { + operation.setDataBinding(nonDefaultDataBindingName); + } + } +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.java new file mode 100644 index 0000000000..e33b7ffbfa --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.databinding.transformers; + +import java.lang.reflect.Array; + +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.osoa.sca.annotations.Reference; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + */ +public class Array2ArrayTransformer extends BaseTransformer implements PullTransformer { + + protected Mediator mediator; + + public Array2ArrayTransformer() { + super(); + } + + /** + * @param mediator the mediator to set + */ + @Reference + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + @Override + public String getSourceDataBinding() { + return "java:array"; + } + + @Override + public String getTargetDataBinding() { + return "java:array"; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + @SuppressWarnings("unchecked") + public Object transform(Object array, TransformationContext context) { + try { + if (array == null) { + return null; + } + DataType sourceType = context.getSourceDataType(); + DataType targetType = context.getTargetDataType(); + int length = Array.getLength(array); + Object targetArray = Array.newInstance(targetType.getPhysical().getComponentType(), length); + for (int i = 0; i < length; i++) { + Object sourceItem = Array.get(array, i); + Object targetItem = + mediator.mediate(sourceItem, sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + Array.set(targetArray, i, targetItem); + } + return targetArray; + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java new file mode 100644 index 0000000000..0c1721ae08 --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.databinding.transformers; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; + +/** + * This is a special transformer to transform the exception from one IDL to the + * other one + */ +public class Exception2ExceptionTransformer extends BaseTransformer implements + PullTransformer { + + protected Mediator mediator; + protected FaultExceptionMapper faultExceptionMapper; + + public Exception2ExceptionTransformer(Mediator mediator, FaultExceptionMapper faultExceptionMapper) { + super(); + this.mediator = mediator; + this.faultExceptionMapper = faultExceptionMapper; + } + + public Exception2ExceptionTransformer() { + super(); + } + + @Override + public String getSourceDataBinding() { + return DataBinding.IDL_FAULT; + } + + @Override + public String getTargetDataBinding() { + return DataBinding.IDL_FAULT; + } + + /** + * @param mediator the mediator to set + */ + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getSourceType() + */ + @Override + protected Class getSourceType() { + return Throwable.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getTargetType() + */ + @Override + protected Class getTargetType() { + return Throwable.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10000; + } + + @SuppressWarnings("unchecked") + public Throwable transform(Throwable source, TransformationContext context) { + DataType sourceType = context.getSourceDataType(); + + DataType targetType = context.getTargetDataType(); + + Object sourceFaultInfo = faultExceptionMapper.getFaultInfo(source, sourceType.getLogical().getPhysical()); + Object targetFaultInfo = + mediator.mediate(sourceFaultInfo, sourceType.getLogical(), targetType.getLogical(), context.getMetadata()); + + Throwable targetException = + faultExceptionMapper.wrapFaultInfo(targetType, source.getMessage(), targetFaultInfo, source.getCause()); + + // FIXME + return targetException == null ? source : targetException; + + } + + public void setFaultExceptionMapper(FaultExceptionMapper faultExceptionMapper) { + this.faultExceptionMapper = faultExceptionMapper; + } +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java new file mode 100644 index 0000000000..b8ec19b985 --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java @@ -0,0 +1,213 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.databinding.transformers; + +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.osoa.sca.annotations.Reference; + +/** + * This is a special transformer to transform the input from one IDL to the + * other one + */ +public class Input2InputTransformer extends BaseTransformer implements + PullTransformer { + private static final Logger logger = Logger.getLogger(Input2InputTransformer.class.getName()); + + protected Mediator mediator; + + public Input2InputTransformer() { + super(); + } + + @Override + public String getSourceDataBinding() { + return DataBinding.IDL_INPUT; + } + + @Override + public String getTargetDataBinding() { + return DataBinding.IDL_INPUT; + } + + /** + * @param mediator the mediator to set + */ + @Reference + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10000; + } + + @SuppressWarnings("unchecked") + public Object[] transform(Object[] source, TransformationContext context) { + DataType> sourceType = context.getSourceDataType(); + Operation sourceOp = context.getSourceOperation(); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle(); + + WrapperHandler sourceWrapperHandler = null; + String sourceDataBinding = getDataBinding(sourceOp); + sourceWrapperHandler = getWrapperHandler(sourceDataBinding, sourceWrapped); + + DataType> targetType = context.getTargetDataType(); + Operation targetOp = (Operation)context.getTargetOperation(); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle(); + WrapperHandler targetWrapperHandler = null; + String targetDataBinding = getDataBinding(targetOp); + targetWrapperHandler = getWrapperHandler(targetDataBinding, targetWrapped); + + if ((!sourceWrapped) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + ElementInfo wrapperElement = wrapper.getInputWrapperElement(); + + if (source == null) { + Object targetWrapper = targetWrapperHandler.create(wrapperElement, context); + return new Object[] {targetWrapper}; + } + + // If the source can be wrapped, wrapped it first + if (sourceWrapperHandler != null) { + DataType sourceWrapperType = + sourceWrapperHandler.getWrapperType(wrapperElement, wrapper.getInputChildElements(), context); + if (sourceWrapperType != null) { + Object sourceWrapper = sourceWrapperHandler.create(wrapperElement, context); + if (sourceWrapper != null) { + for (int i = 0; i < source.length; i++) { + ElementInfo argElement = wrapper.getInputChildElements().get(i); + sourceWrapperHandler.setChild(sourceWrapper, i, argElement, source[i]); + } + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceWrapperType, targetType.getLogical().get(0), context + .getMetadata()); + return new Object[] {targetWrapper}; + } + } + } + // Fall back to child by child transformation + Object targetWrapper = targetWrapperHandler.create(wrapperElement, context); + List argTypes = wrapper.getUnwrappedInputType().getLogical(); + + for (int i = 0; i < source.length; i++) { + ElementInfo argElement = wrapper.getInputChildElements().get(i); + DataType argType = argTypes.get(i); + Object child = source[i]; + child = mediator.mediate(source[i], sourceType.getLogical().get(i), argType, context.getMetadata()); + targetWrapperHandler.setChild(targetWrapper, i, argElement, child); + } + return new Object[] {targetWrapper}; + + } else if (sourceWrapped && (!targetWrapped)) { + // Wrapped to Unwrapped + Object sourceWrapper = source[0]; + Object[] target = null; + + List childElements = sourceOp.getWrapper().getInputChildElements(); + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement(); + // FIXME: This is a workaround for the wsdless support as it passes in child elements + // under the wrapper that only matches by position + if (sourceWrapperHandler.isInstance(sourceWrapper, wrapperElement, childElements, context)) { + DataType targetWrapperType = + targetWrapperHandler.getWrapperType(wrapperElement, childElements, context); + if (targetWrapperType != null) { + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceType.getLogical().get(0), targetWrapperType, context + .getMetadata()); + target = targetWrapperHandler.getChildren(targetWrapper, childElements, context).toArray(); + return target; + } + } + } + Object[] sourceChildren = sourceWrapperHandler.getChildren(sourceWrapper, childElements, context).toArray(); + target = new Object[sourceChildren.length]; + for (int i = 0; i < sourceChildren.length; i++) { + DataType childType = sourceOp.getWrapper().getUnwrappedInputType().getLogical().get(i); + target[i] = + mediator.mediate(sourceChildren[i], childType, targetType.getLogical().get(i), context + .getMetadata()); + } + return target; + } else { + // Assuming wrapper to wrapper conversion can be handled here as well + Object[] newArgs = new Object[source.length]; + for (int i = 0; i < source.length; i++) { + Object child = + mediator.mediate(source[i], sourceType.getLogical().get(i), targetType.getLogical().get(i), context + .getMetadata()); + newArgs[i] = child; + } + return newArgs; + } + } + + private WrapperHandler getWrapperHandler(String dataBindingId, boolean required) { + WrapperHandler wrapperHandler = null; + if (dataBindingId != null) { + DataBinding dataBinding = mediator.getDataBindings().getDataBinding(dataBindingId); + wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + } + if (wrapperHandler == null && required) { + throw new TransformationException("No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + + private String getDataBinding(Operation operation) { + return operation.getDataBinding(); + } + +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java new file mode 100644 index 0000000000..7fed2e5eaa --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.databinding.transformers; + +import java.util.List; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.osoa.sca.annotations.Reference; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + */ +public class Output2OutputTransformer extends BaseTransformer implements + PullTransformer { + + protected Mediator mediator; + + /** + * @param wrapperHandler + */ + public Output2OutputTransformer() { + super(); + } + + /** + * @param mediator the mediator to set + */ + @Reference + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + @Override + public String getSourceDataBinding() { + return DataBinding.IDL_OUTPUT; + } + + @Override + public String getTargetDataBinding() { + return DataBinding.IDL_OUTPUT; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.impl.BaseTransformer#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + private String getDataBinding(Operation operation) { + return operation.getDataBinding(); + } + + private WrapperHandler getWrapperHandler(String dataBindingId, boolean required) { + WrapperHandler wrapperHandler = null; + if (dataBindingId != null) { + DataBinding dataBinding = mediator.getDataBindings().getDataBinding(dataBindingId); + wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + } + if (wrapperHandler == null && required) { + throw new TransformationException("No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + + @SuppressWarnings("unchecked") + public Object transform(Object response, TransformationContext context) { + try { + DataType sourceType = context.getSourceDataType(); + Operation sourceOp = context.getSourceOperation(); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle(); + + WrapperHandler sourceWrapperHandler = null; + String sourceDataBinding = getDataBinding(sourceOp); + sourceWrapperHandler = getWrapperHandler(sourceDataBinding, sourceWrapped); + + DataType targetType = context.getTargetDataType(); + Operation targetOp = (Operation)context.getTargetOperation(); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle(); + WrapperHandler targetWrapperHandler = null; + String targetDataBinding = getDataBinding(targetOp); + targetWrapperHandler = getWrapperHandler(targetDataBinding, targetWrapped); + + if ((!sourceWrapped) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + ElementInfo wrapperElement = wrapper.getOutputWrapperElement(); + List childElements = wrapper.getOutputChildElements(); + + // If the source can be wrapped, wrapped it first + if (sourceWrapperHandler != null) { + DataType sourceWrapperType = + sourceWrapperHandler.getWrapperType(wrapperElement, childElements, context); + if (sourceWrapperType != null) { + Object sourceWrapper = sourceWrapperHandler.create(wrapperElement, context); + if (sourceWrapper != null) { + if (!childElements.isEmpty()) { + // Set the return value + ElementInfo returnElement = wrapper.getOutputChildElements().get(0); + sourceWrapperHandler.setChild(sourceWrapper, 0, returnElement, response); + } + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceWrapperType, targetType.getLogical(), context + .getMetadata()); + return targetWrapper; + } + } + } + Object targetWrapper = targetWrapperHandler.create(wrapper.getOutputWrapperElement(), context); + + if (childElements.isEmpty()) { + // void output + return targetWrapper; + } + ElementInfo argElement = childElements.get(0); + DataType argType = wrapper.getUnwrappedOutputType(); + Object child = response; + child = mediator.mediate(response, sourceType.getLogical(), argType, context.getMetadata()); + targetWrapperHandler.setChild(targetWrapper, 0, argElement, child); + return targetWrapper; + } else if (sourceWrapped && (!targetWrapped)) { + // Wrapped to Unwrapped + Object sourceWrapper = response; + List childElements = sourceOp.getWrapper().getOutputChildElements(); + if (childElements.isEmpty()) { + // The void output + return null; + } + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getOutputWrapperElement(); + + // FIXME: This is a workaround for the wsdless support as it passes in child elements + // under the wrapper that only matches by position + if (sourceWrapperHandler.isInstance(sourceWrapper, wrapperElement, childElements, context)) { + DataType targetWrapperType = + targetWrapperHandler.getWrapperType(wrapperElement, childElements, context); + if (targetWrapperType != null) { + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceType.getLogical(), targetWrapperType, context + .getMetadata()); + return targetWrapperHandler.getChildren(targetWrapper, childElements, context).get(0); + } + } + } + Object child = sourceWrapperHandler.getChildren(sourceWrapper, childElements, context).get(0); + DataType childType = sourceOp.getWrapper().getUnwrappedOutputType(); + return mediator.mediate(child, childType, targetType.getLogical(), context.getMetadata()); + } else { + // FIXME: Do we want to handle wrapped to wrapped? + return mediator.mediate(response, sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + } + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java new file mode 100644 index 0000000000..0dbe92dfa4 --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.databinding.wire; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +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.Phase; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; + +/** + * This processor is responsible to add an interceptor to invocation chain if + * the source and target operations have different databinding requirements + * + * @version $Rev: 632064 $ $Date: 2008-02-28 09:18:51 -0800 (Thu, 28 Feb 2008) $ + */ +public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { + private Mediator mediator; + private DataBindingExtensionPoint dataBindings; + private FaultExceptionMapper faultExceptionMapper; + + public DataBindingRuntimeWireProcessor(Mediator mediator, + DataBindingExtensionPoint dataBindings, + FaultExceptionMapper faultExceptionMapper) { + super(); + this.mediator = mediator; + this.dataBindings = dataBindings; + this.faultExceptionMapper = faultExceptionMapper; + } + + public boolean isTransformationRequired(DataType source, DataType target) { + if (source == null || target == null) { // void return type + return false; + } + if (source == target) { + return false; + } + + // Output type can be null + if (source == null && target == null) { + return false; + } else if (source == null || target == null) { + return true; + } + String sourceDataBinding = source.getDataBinding(); + String targetDataBinding = target.getDataBinding(); + if (sourceDataBinding == targetDataBinding) { + return false; + } + if (sourceDataBinding == null || targetDataBinding == null) { + // TODO: If any of the databinding is null, then no transformation + return false; + } + return !sourceDataBinding.equals(targetDataBinding); + } + + public boolean isTransformationRequired(Operation source, Operation target) { + if (source == target) { + return false; + } + + if (source.isWrapperStyle() != target.isWrapperStyle()) { + return true; + } + + // Check output type + DataType sourceOutputType = source.getOutputType(); + DataType targetOutputType = target.getOutputType(); + + // Note the target output type is now the source for checking + // compatibility + if (isTransformationRequired(targetOutputType, sourceOutputType)) { + return true; + } + + List sourceInputType = source.getInputType().getLogical(); + List targetInputType = target.getInputType().getLogical(); + + int size = sourceInputType.size(); + if (size != targetInputType.size()) { + // TUSCANY-1682: The wrapper style may have different arguments + return true; + } + for (int i = 0; i < size; i++) { + if (isTransformationRequired(sourceInputType.get(i), targetInputType.get(i))) { + return true; + } + } + + return false; + } + + private boolean isTransformationRequired(InterfaceContract sourceContract, + Operation sourceOperation, + InterfaceContract targetContract, + Operation targetOperation) { + if (targetContract == null) { + targetContract = sourceContract; + } + if (sourceContract == targetContract) { + return false; + } + return isTransformationRequired(sourceOperation, targetOperation); + } + + public void process(RuntimeWire wire) { + InterfaceContract sourceContract = wire.getSource().getInterfaceContract(); + InterfaceContract targetContract = wire.getTarget().getInterfaceContract(); + if (targetContract == null) { + targetContract = sourceContract; + } + + if (!sourceContract.getInterface().isRemotable()) { + return; + } + List chains = wire.getInvocationChains(); + for (InvocationChain chain : chains) { + Operation sourceOperation = chain.getSourceOperation(); + Operation targetOperation = chain.getTargetOperation(); + + Interceptor interceptor = null; + if (isTransformationRequired(sourceContract, sourceOperation, targetContract, targetOperation)) { + // Add the interceptor to the source side because multiple + // references can be wired to the same service + interceptor = + new DataTransformationInterceptor(wire, sourceOperation, targetOperation, mediator, + faultExceptionMapper); + } else { + // assume pass-by-values copies are required if interfaces are remotable and there is no data binding + // transformation, i.e. a transformation will result in a copy so another pass-by-value copy is unnecessary + if (isRemotable(chain, sourceOperation, targetOperation)) { + interceptor = + new PassByValueInterceptor(dataBindings, faultExceptionMapper, chain, targetOperation); + } + } + if (interceptor != null) { + String phase = + (wire.getSource().getContract() instanceof ComponentReference) ? Phase.REFERENCE_INTERFACE + : Phase.SERVICE_INTERFACE; + chain.addInterceptor(phase, interceptor); + } + } + + } + + /** + * Pass-by-value copies are required if the interfaces are remotable unless the + * implementation uses the @AllowsPassByReference annotation. + */ + protected boolean isRemotable(InvocationChain chain, Operation sourceOperation, Operation targetOperation) { + if (!sourceOperation.getInterface().isRemotable()) { + return false; + } + if (!targetOperation.getInterface().isRemotable()) { + return false; + } + return true; + } + +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java new file mode 100644 index 0000000000..193ba98283 --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.databinding.wire; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.FaultException; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +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.osoa.sca.ServiceRuntimeException; + +/** + * An interceptor to transform data across databindings on the wire + * + * @version $Rev: 643467 $ $Date: 2008-04-01 08:12:08 -0800 (Tue, 01 Apr 2008) $ + */ +public class DataTransformationInterceptor implements Interceptor, DataExchangeSemantics { + private Invoker next; + + private Operation sourceOperation; + + private Operation targetOperation; + private RuntimeWire wire; + private Mediator mediator; + private FaultExceptionMapper faultExceptionMapper; + + public DataTransformationInterceptor(RuntimeWire wire, + Operation sourceOperation, + Operation targetOperation, + Mediator mediator, + FaultExceptionMapper faultExceptionMapper) { + super(); + this.sourceOperation = sourceOperation; + this.targetOperation = targetOperation; + this.mediator = mediator; + this.wire = wire; + this.faultExceptionMapper = faultExceptionMapper; + } + + public Invoker getNext() { + return next; + } + + public Message invoke(Message msg) { + Object input = transform(msg.getBody(), sourceOperation.getInputType(), targetOperation.getInputType(), false); + msg.setBody(input); + Message resultMsg = next.invoke(msg); + Object result = resultMsg.getBody(); + if (sourceOperation.isNonBlocking()) { + // Not to reset the message body + return resultMsg; + } + + // FIXME: Should we fix the Operation model so that getOutputType + // returns DataType>? + DataType targetType = + new DataTypeImpl(DataBinding.IDL_OUTPUT, Object.class, targetOperation.getOutputType()); + + DataType sourceType = + new DataTypeImpl(DataBinding.IDL_OUTPUT, Object.class, sourceOperation.getOutputType()); + + if (resultMsg.isFault()) { + + // FIXME: We need to figure out what fault type it is and then + // transform it + // back the source fault type + // throw new InvocationRuntimeException((Throwable) result); + + if ((result instanceof Exception) && !(result instanceof RuntimeException)) { + // FIXME: How to match fault data to a fault type for the + // operation? + + // If the result is from an InvocationTargetException look at + // the actual cause. + if (result instanceof InvocationTargetException) { + result = ((InvocationTargetException)result).getCause(); + } + DataType targetDataType = null; + for (DataType exType : targetOperation.getFaultTypes()) { + if (((Class)exType.getPhysical()).isInstance(result)) { + if (result instanceof FaultException) { + DataType faultType = (DataType)exType.getLogical(); + if (((FaultException)result).isMatchingType(faultType.getLogical())) { + targetDataType = exType; + break; + } + } else { + targetDataType = exType; + break; + } + } + } + + /* + if (targetDataType == null) { + // Not a business exception + return resultMsg; + } + */ + + DataType targetFaultType = getFaultType(targetDataType); + if (targetFaultType == null) { + // No matching fault type, it's a system exception + Throwable cause = (Throwable) result; + throw new ServiceRuntimeException(cause); + } + + // FIXME: How to match a source fault type to a target fault + // type? + DataType sourceDataType = null; + DataType sourceFaultType = null; + for (DataType exType : sourceOperation.getFaultTypes()) { + DataType faultType = getFaultType(exType); + // Match by the QName (XSD element) of the fault type + if (faultType != null && typesMatch(targetFaultType.getLogical(), faultType.getLogical())) { + sourceDataType = exType; + sourceFaultType = faultType; + break; + } + } + + if (sourceFaultType == null) { + // No matching fault type, it's a system exception + Throwable cause = (Throwable) result; + throw new ServiceRuntimeException(cause); + } + + Object newResult = + transformException(result, targetDataType, sourceDataType, targetFaultType, sourceFaultType); + if (newResult != result) { + resultMsg.setFaultBody(newResult); + } + } + + } else { + assert !(result instanceof Throwable) : "Expected messages that are not throwable " + result; + + Object newResult = transform(result, targetType, sourceType, true); + if (newResult != result) { + resultMsg.setBody(newResult); + } + } + + return resultMsg; + } + + private Object transform(Object source, DataType sourceType, DataType targetType, boolean isResponse) { + if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) { + return source; + } + Map metadata = new HashMap(); + metadata.put("source.operation", isResponse ? targetOperation : sourceOperation); + metadata.put("target.operation", isResponse ? sourceOperation : targetOperation); + metadata.put("wire", wire); + return mediator.mediate(source, sourceType, targetType, metadata); + } + + private DataType getFaultType(DataType exceptionType) { + return exceptionType == null ? null : (DataType)exceptionType.getLogical(); + } + + private boolean typesMatch(Object first, Object second) { + if (first.equals(second)) { + return true; + } + if (first instanceof XMLType && second instanceof XMLType) { + XMLType t1 = (XMLType)first; + XMLType t2 = (XMLType)second; + return matches(t1.getElementName(), t2.getElementName()) || matches(t1.getTypeName(), t2.getTypeName()); + } + return false; + } + + /** + * @param qn1 + * @param qn2 + */ + private boolean matches(QName qn1, QName qn2) { + if (qn1 == qn2) { + return true; + } + if (qn1 == null || qn2 == null) { + return false; + } + String ns1 = qn1.getNamespaceURI(); + String ns2 = qn2.getNamespaceURI(); + String e1 = qn1.getLocalPart(); + String e2 = qn2.getLocalPart(); + if (e1.equals(e2) && (ns1.equals(ns2) || ns1.equals(ns2 + "/") || ns2.equals(ns1 + "/"))) { + // Tolerating the trailing / which is required by JAX-WS java package --> xml ns mapping + return true; + } + return false; + } + + /** + * @param source The source exception + * @param sourceExType The data type for the source exception + * @param targetExType The data type for the target exception + * @param sourceType The fault type for the source + * @param targetType The fault type for the target + * @return + */ + private Object transformException(Object source, + DataType sourceExType, + DataType targetExType, + DataType sourceType, + DataType targetType) { + if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) { + return source; + } + Map metadata = new HashMap(); + metadata.put("source.operation", targetOperation); + metadata.put("target.operation", sourceOperation); + metadata.put("wire", wire); + DataType eSourceDataType = + new DataTypeImpl("idl:fault", sourceExType.getPhysical(), sourceType); + DataType eTargetDataType = + new DataTypeImpl("idl:fault", targetExType.getPhysical(), targetType); + + return mediator.mediate(source, eSourceDataType, eTargetDataType, metadata); + } + + public void setNext(Invoker next) { + this.next = next; + } + + public boolean allowsPassByReference() { + return true; + } + +} diff --git a/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java new file mode 100644 index 0000000000..3e0741d0a7 --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.databinding.wire; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +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.osoa.sca.ServiceRuntimeException; + +/** + * Implementation of an interceptor that enforces pass-by-value semantics + * on operation invocations by copying the operation input and output data. + * + * @version $Rev: 639276 $ $Date: 2008-03-20 05:02:00 -0800 (Thu, 20 Mar 2008) $ + */ +public class PassByValueInterceptor implements Interceptor { + + private DataBindingExtensionPoint dataBindings; + private FaultExceptionMapper faultExceptionMapper; + + private DataBinding[] inputDataBindings; + private DataBinding outputDataBinding; + private DataBinding javaBeanDataBinding; + private DataBinding jaxbDataBinding; + private Operation operation; + private Invoker nextInvoker; + private InvocationChain chain; + + /** + * Constructs a new PassByValueInterceptor. + * @param dataBindings databinding extension point + * @param operation the intercepted operation + */ + public PassByValueInterceptor(DataBindingExtensionPoint dataBindings, + FaultExceptionMapper faultExceptionMapper, + InvocationChain chain, + Operation operation) { + this.chain = chain; + this.operation = operation; + + // Cache data bindings to use + this.dataBindings = dataBindings; + this.faultExceptionMapper = faultExceptionMapper; + + jaxbDataBinding = dataBindings.getDataBinding(JAXBDataBinding.NAME); + javaBeanDataBinding = dataBindings.getDataBinding(JavaBeansDataBinding.NAME); + + // Determine the input databindings + if (operation.getInputType() != null) { + List inputTypes = operation.getInputType().getLogical(); + inputDataBindings = new DataBinding[inputTypes.size()]; + int i = 0; + for (DataType inputType : inputTypes) { + String id = inputType.getDataBinding(); + inputDataBindings[i++] = dataBindings.getDataBinding(id); + } + } + + // Determine the output databinding + if (operation.getOutputType() != null) { + String id = operation.getOutputType().getDataBinding(); + outputDataBinding = dataBindings.getDataBinding(id); + } + } + + public Message invoke(Message msg) { + if (chain.allowsPassByReference()) { + return nextInvoker.invoke(msg); + } + + msg.setBody(copy((Object[])msg.getBody(), inputDataBindings)); + + Message resultMsg = nextInvoker.invoke(msg); + + if (!msg.isFault() && operation.getOutputType() != null) { + resultMsg.setBody(copy(resultMsg.getBody(), outputDataBinding)); + } + + if (msg.isFault()) { + msg.setFaultBody(copyFault(msg.getBody())); + } + return resultMsg; + } + + private Object copyFault(Object fault) { + if (faultExceptionMapper == null) { + return fault; + } + Throwable ex = (Throwable)fault; + DataType exType = + new DataTypeImpl(ex.getClass(), new DataTypeImpl(ex.getClass(), XMLType.UNKNOWN)); + faultExceptionMapper.introspectFaultDataType(exType); + DataType faultType = exType.getLogical(); + Object faultInfo = faultExceptionMapper.getFaultInfo(ex, faultType.getPhysical()); + faultInfo = copy(faultInfo, dataBindings.getDataBinding(faultType.getDataBinding())); + fault = faultExceptionMapper.wrapFaultInfo(exType, ex.getMessage(), faultInfo, ex.getCause()); + return fault; + } + + /** + * Copy an array of data objects passed to an operation + * @param data array of objects to copy + * @return the copy + */ + private Object[] copy(Object[] data, DataBinding[] dataBindings) { + if (data == null) { + return null; + } + Object[] copy = new Object[data.length]; + Map map = new IdentityHashMap(); + for (int i = 0; i < data.length; i++) { + Object arg = data[i]; + if (arg == null) { + copy[i] = null; + } else { + Object copiedArg = map.get(arg); + if (copiedArg != null) { + copy[i] = copiedArg; + } else { + copiedArg = copy(arg, dataBindings[i]); + map.put(arg, copiedArg); + copy[i] = copiedArg; + } + } + } + return copy; + } + + /** + * Copy data using the specified databinding. + * @param data input data + * @param dataBinding databinding to use + * @return a copy of the data + */ + private Object copy(Object data, DataBinding dataBinding) { + if (data == null) { + return null; + } + + // If no databinding was specified, introspect the given arg to + // determine its databinding + if (dataBinding == null) { + DataType dataType = dataBindings.introspectType(data); + if (dataType != null) { + String db = dataType.getDataBinding(); + dataBinding = dataBindings.getDataBinding(db); + if (dataBinding == null && db != null) { + return data; + } + } + if (dataBinding == null) { + + // Default to the JavaBean databinding + dataBinding = javaBeanDataBinding; + } + } + + // Use the JAXB databinding to copy non-Serializable data + if (dataBinding == javaBeanDataBinding) { + + // If the input data is an array containing non Serializable elements + // use JAXB + Class clazz = data.getClass(); + if (clazz.isArray()) { + if (Array.getLength(data) != 0) { + Object element = Array.get(data, 0); + if (element != null && !(element instanceof Serializable)) { + dataBinding = jaxbDataBinding; + } + } + } else { + + // If the input data is not Serializable use JAXB + if (!(data instanceof Serializable)) { + dataBinding = jaxbDataBinding; + } + + if (data instanceof Cloneable) { + Method clone; + try { + clone = data.getClass().getMethod("clone", (Class[])null); + try { + return clone.invoke(data, (Object[])null); + } catch (InvocationTargetException e) { + if (e.getTargetException() instanceof CloneNotSupportedException) { + // Ignore + } else { + throw new ServiceRuntimeException(e); + } + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } catch (NoSuchMethodException e) { + // Ignore it + } + } + } + } + + Object copy = dataBinding.copy(data); + return copy; + } + + public Invoker getNext() { + return nextInvoker; + } + + public void setNext(Invoker next) { + this.nextInvoker = next; + } + +} diff --git a/branches/sca-android/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator b/branches/sca-android/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator new file mode 100644 index 0000000000..baba638c9b --- /dev/null +++ b/branches/sca-android/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator @@ -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. +# Implementation class for the ExtensionActivator +org.apache.tuscany.sca.core.databinding.module.DataBindingModuleActivator diff --git a/branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessorTestCase.java b/branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessorTestCase.java new file mode 100644 index 0000000000..ea08166dfe --- /dev/null +++ b/branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessorTestCase.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.databinding.processor; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.annotation.DataBinding; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.annotations.Remotable; +import org.w3c.dom.Node; + +/** + * + */ +public class DataBindingJavaInterfaceProcessorTestCase extends TestCase { + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + } + + /** + * @throws InvalidServiceContractException + */ + public final void testVisitInterface() throws InvalidInterfaceException { + DataBindingExtensionPoint registry = new DefaultDataBindingExtensionPoint(); + DataBindingJavaInterfaceProcessor processor = new DataBindingJavaInterfaceProcessor(registry); + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + + JavaInterface contract = javaFactory.createJavaInterface(); + contract.setJavaClass(MockInterface.class); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(contract); + Operation operation = newOperation("call"); + Operation operation1 = newOperation("call1"); + contract.getOperations().add(operation); + contract.getOperations().add(operation1); + contract.setRemotable(true); + processor.visitInterface(contract); + // Assert.assertEquals("org.w3c.dom.Node", contract.getDataBinding()); + // Assert.assertEquals("org.w3c.dom.Node", + // contract.getOperations().get("call").getDataBinding()); + // Assert.assertEquals("xml:string", + // contract.getOperations().get("call1").getDataBinding()); + } + + @DataBinding("org.w3c.dom.Node") + @Remotable + public static interface MockInterface { + Node call(Node msg); + + @DataBinding("xml:string") + String call1(String msg); + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} diff --git a/branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/transformers/IDLTransformerTestCase.java.fixme b/branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/transformers/IDLTransformerTestCase.java.fixme new file mode 100644 index 0000000000..be2f3fe7cb --- /dev/null +++ b/branches/sca-android/core-databinding/src/test/java/org/apache/tuscany/sca/core/databinding/transformers/IDLTransformerTestCase.java.fixme @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.transformers; + +import static org.apache.tuscany.spi.databinding.DataBinding.IDL_INPUT; +import static org.apache.tuscany.spi.databinding.DataBinding.IDL_OUTPUT; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.databinding.impl.DataBindingRegistryImpl; +import org.apache.tuscany.databinding.impl.MediatorImpl; +import org.apache.tuscany.databinding.impl.TransformationContextImpl; +import org.apache.tuscany.databinding.impl.TransformerRegistryImpl; +import org.apache.tuscany.databinding.javabeans.DOMNode2JavaBeanTransformer; +import org.apache.tuscany.databinding.javabeans.JavaBean2DOMNodeTransformer; +import org.apache.tuscany.databinding.xml.DOMDataBinding; +import org.apache.tuscany.databinding.xml.Node2String; +import org.apache.tuscany.databinding.xml.String2Node; +import org.apache.tuscany.interfacedef.DataType; +import org.apache.tuscany.interfacedef.Operation; +import org.apache.tuscany.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.interfacedef.impl.OperationImpl; +import org.apache.tuscany.interfacedef.util.ElementInfo; +import org.apache.tuscany.interfacedef.util.TypeInfo; +import org.apache.tuscany.interfacedef.util.WrapperInfo; +import org.apache.tuscany.interfacedef.util.XMLType; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class IDLTransformerTestCase extends TestCase { + private static final String IPO_XML = "" + "" + + " " + + " Helen Zoe" + + " 47 Eden Street" + + " Cambridge" + + " CB1 1JR" + + " " + + " " + + " Robert Smith" + + " 8 Oak Avenue" + + " Old Town" + + " PA" + + " 95819" + + " " + + " " + + " " + + " Lapis necklace" + + " 1" + + " 99.95" + + " Want this for the holidays" + + " 1999-12-05" + + " " + + " " + + ""; + + private static final String URI_ORDER_XSD = "http://example.com/order.xsd"; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransform() throws Exception { + List types0 = new ArrayList(); + DataType wrapperType = new DataTypeImpl(null, Object.class, + new XMLType(new QName(URI_ORDER_XSD, + "checkOrderStatus"), null)); + types0.add(wrapperType); + DataType> inputType0 = new DataTypeImpl>(IDL_INPUT, + Object[].class, types0); + + List types1 = new ArrayList(); + DataType customerIdType = new DataTypeImpl( + null, + Object.class, + new XMLType( + new QName(URI_ORDER_XSD, "customerId"), + null)); + DataType orderType = new DataTypeImpl(null, Object.class, + new XMLType(new QName(URI_ORDER_XSD, "order"), null)); + DataType flagType = new DataTypeImpl(null, Object.class, new XMLType(new QName(URI_ORDER_XSD, + "flag"), null)); + types1.add(customerIdType); + types1.add(orderType); + types1.add(flagType); + + DataType statusType = new DataTypeImpl(null, Object.class, + new XMLType(new QName(URI_ORDER_XSD, "status"), null)); + DataType responseType = new DataTypeImpl(null, Object.class, + new XMLType(new QName(URI_ORDER_XSD, + "checkOrderStatusResponse"), + null)); + + Operation op = new OperationImpl("checkOrderStatus"); + op.setInputType(inputType0); + op.setOutputType(responseType); +// op.setDataBinding(DOMDataBinding.NAME); +// +// inputType0.setOperation(op); + op.setWrapperStyle(true); + ElementInfo inputElement = new ElementInfo(new QName(URI_ORDER_XSD, "checkOrderStatus"), new TypeInfo(null, + false, + null)); +// wrapperType.setMetadata(ElementInfo.class.getName(), inputElement); + + ElementInfo customerId = new ElementInfo(new QName("", "customerId"), + SimpleTypeMapperExtension.XSD_SIMPLE_TYPES.get("string")); + ElementInfo order = new ElementInfo(new QName("", "order"), new TypeInfo(new QName(URI_ORDER_XSD), false, null)); + ElementInfo flag = new ElementInfo(new QName("", "flag"), SimpleTypeMapperExtension.XSD_SIMPLE_TYPES.get("int")); + +// customerIdType.setMetadata(ElementInfo.class.getName(), customerId); +// orderType.setMetadata(ElementInfo.class.getName(), order); +// flagType.setMetadata(ElementInfo.class.getName(), flag); +// +// customerIdType.setOperation(op); +// orderType.setOperation(op); +// flagType.setOperation(op); + + List inputElements = new ArrayList(); + inputElements.add(customerId); + inputElements.add(order); + inputElements.add(flag); + + ElementInfo statusElement = new ElementInfo(new QName("", "status"), SimpleTypeMapperExtension.XSD_SIMPLE_TYPES + .get("string")); + +// statusType.setMetadata(ElementInfo.class.getName(), statusElement); +// statusType.setOperation(op); + + List outputElements = new ArrayList(); + outputElements.add(statusElement); + + ElementInfo outputElement = new ElementInfo(new QName(URI_ORDER_XSD, "checkOrderStatusResponse"), + new TypeInfo(null, false, null)); + +// responseType.setMetadata(ElementInfo.class.getName(), inputElement); +// responseType.setOperation(op); + + WrapperInfo wrapperInfo = new WrapperInfo(DOMDataBinding.NAME, inputElement, outputElement, inputElements, + outputElements); + op.setWrapper(wrapperInfo); +// op.setDataBinding(DOMDataBinding.NAME); + + MediatorImpl m = new MediatorImpl(); + TransformerRegistryImpl tr = new TransformerRegistryImpl(); + tr.registerTransformer(new String2Node()); + tr.registerTransformer(new Node2String()); + tr.registerTransformer(new DOMNode2JavaBeanTransformer()); + tr.registerTransformer(new JavaBean2DOMNodeTransformer()); + m.setTransformerRegistry(tr); + DataBindingRegistry dataBindingRegistry = new DataBindingRegistryImpl(); + dataBindingRegistry.register(new DOMDataBinding()); + m.setDataBindingRegistry(dataBindingRegistry); + + Object[] source = new Object[] {"cust001", IPO_XML, Integer.valueOf(1)}; + Input2InputTransformer t = new Input2InputTransformer(); + t.setMediator(m); + + TransformationContext context = new TransformationContextImpl(); + context.setSourceOperation(op); + List> types = new ArrayList>(); + types.add(new DataTypeImpl(Object.class.getName(), String.class, String.class)); + types.add(new DataTypeImpl("java.lang.String", String.class, String.class)); + types.add(new DataTypeImpl(Object.class.getName(), int.class, int.class)); + DataType>> inputType1 = new DataTypeImpl>>(IDL_INPUT, Object[].class, + types); + context.setSourceDataType(inputType1); + context.setTargetDataType(op.getInputType()); + Object[] results = t.transform(source, context); + assertEquals(1, results.length); + assertTrue(results[0] instanceof Element); + Element element = (Element)results[0]; + assertEquals("http://example.com/order.xsd", element.getNamespaceURI()); + assertEquals("checkOrderStatus", element.getLocalName()); + + TransformationContext context1 = new TransformationContextImpl(); + DataType sourceType = new DataTypeImpl(IDL_OUTPUT, Object.class, op.getOutputType()); + + context1.setSourceDataType(sourceType); + DataType targetType = new DataTypeImpl(IDL_OUTPUT, Object.class, + new DataTypeImpl("java.lang.Object", + String.class, String.class)); + context1.setTargetDataType(targetType); + + Document factory = DOMHelper.newDocument(); + Element responseElement = factory + .createElementNS("http://example.com/order.wsdl", "p:checkOrderStatusResponse"); + Element status = factory.createElement("status"); + responseElement.appendChild(status); + status.appendChild(factory.createTextNode("shipped")); + Output2OutputTransformer t2 = new Output2OutputTransformer(); + t2.setMediator(m); + Object st = t2.transform(responseElement, context1); + assertEquals("shipped", st); + + } + +} diff --git a/branches/sca-android/extensibility/.classpath b/branches/sca-android/extensibility/.classpath new file mode 100644 index 0000000000..4bd80ca1d6 --- /dev/null +++ b/branches/sca-android/extensibility/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/branches/sca-android/extensibility/.project b/branches/sca-android/extensibility/.project new file mode 100644 index 0000000000..7e1a2e5ff6 --- /dev/null +++ b/branches/sca-android/extensibility/.project @@ -0,0 +1,13 @@ + + tuscany-extensibility + Parent POM defining settings that can be used across Tuscany + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/extensibility/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/extensibility/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..af3f96beaa --- /dev/null +++ b/branches/sca-android/extensibility/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:19:21 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/extensibility/DISCLAIMER b/branches/sca-android/extensibility/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/extensibility/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/extensibility/LICENSE b/branches/sca-android/extensibility/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/extensibility/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/branches/sca-android/extensibility/NOTICE b/branches/sca-android/extensibility/NOTICE new file mode 100644 index 0000000000..65c52d01c7 --- /dev/null +++ b/branches/sca-android/extensibility/NOTICE @@ -0,0 +1,5 @@ +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/extensibility/pom.xml b/branches/sca-android/extensibility/pom.xml new file mode 100644 index 0000000000..991ee1aeaf --- /dev/null +++ b/branches/sca-android/extensibility/pom.xml @@ -0,0 +1,31 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-extensibility + Apache Tuscany SCA Extensibility + + diff --git a/branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java b/branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java new file mode 100644 index 0000000000..ff7d215d2e --- /dev/null +++ b/branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDeclaration.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extensibility; + +import java.lang.ref.WeakReference; +import java.net.URL; +import java.util.Map; + +/** + * Service declaration using J2SE Jar service provider spec Classes specified + * inside this declaration are loaded using the ClassLoader used to read the + * configuration file corresponding to this declaration. + */ +public class ServiceDeclaration { + + private WeakReference classLoader; + + private String className; + + private Map attributes; + + /** + * Service declaration constructor + * + * @param className Service implementation class name + * @param classLoader ClassLoader corresponding to this service + * implementation + * @param attributes Optional attributes for this service declaration + */ + public ServiceDeclaration(String className, ClassLoader classLoader, Map attributes) { + + this.className = className; + this.classLoader = new WeakReference(classLoader); + this.attributes = attributes; + } + + /** + * Load this service implementation class + * + * @return Class + * @throws ClassNotFoundException + */ + @SuppressWarnings("unchecked") + public Class loadClass() throws ClassNotFoundException { + + return Class.forName(className, true, classLoader.get()); + } + + /** + * Load another class using the ClassLoader of this service implementation + * + * @param anotherClassName + * @return Class + * @throws ClassNotFoundException + */ + public Class loadClass(String anotherClassName) throws ClassNotFoundException { + + return Class.forName(anotherClassName, true, classLoader.get()); + } + + /** + * Return the resource corresponding to this service implementation class + * + * @return resource URL + */ + public URL getResource() { + return classLoader.get().getResource(className); + } + + /** + * ClassLoader associated with this service declaration + * + * @return ClassLoader + */ + public ClassLoader getClassLoader() { + return classLoader.get(); + } + + /** + * Service implementation class corresponding to this declaration + * + * @return The Service implementation class corresponding to this declaration + */ + public String getClassName() { + return className; + } + + /** + * Attributes specified for this declaration + * + * @return attributes + */ + public Map getAttributes() { + return attributes; + } + + /** + * Equals method used to ensure that each service declaration is stored only + * once in a set of declarations. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof ServiceDeclaration)) + return false; + ServiceDeclaration s = (ServiceDeclaration)o; + if (!className.equals(s.className)) + return false; + else if (!classLoader.equals(s.classLoader)) + return false; + else if (attributes == null) + return s.attributes == null; + else + return attributes.equals(s.attributes); + + } + +} diff --git a/branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java b/branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java new file mode 100644 index 0000000000..a7358590de --- /dev/null +++ b/branches/sca-android/extensibility/src/main/java/org/apache/tuscany/sca/extensibility/ServiceDiscovery.java @@ -0,0 +1,436 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.extensibility; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Service discovery for Tuscany based on J2SE Jar service provider spec. + * Services are described using configuration files in META-INF/services. + * Service description specifies a class name followed by optional properties. + * Multi-ClassLoader environments are supported through a ClassLoader + * registration API + */ +public class ServiceDiscovery { + private final static Logger logger = Logger + .getLogger(ServiceDiscovery.class.getName()); + + private static ServiceDiscovery instance; + + private HashSet registeredClassLoaders; + + /** + * Get an instance of Service discovery, one instance is created per + * ClassLoader that this class is loaded from + * + * @return + */ + public static ServiceDiscovery getInstance() { + + if (instance == null) { + instance = new ServiceDiscovery(); + instance.registeredClassLoaders = new HashSet(); + instance.registeredClassLoaders.add(ServiceDiscovery.class + .getClassLoader()); + } + return instance; + } + + /** + * Register a ClassLoader with this discovery mechanism. Tuscany extension + * ClassLoaders are registered here. + * + * @param classLoader + */ + public void registerClassLoader(ClassLoader classLoader) { + registeredClassLoaders.add(classLoader); + } + + /** + * Get all service declarations for this name + * + * @param name + * @return set of service declarations + * @throws IOException + */ + public Set getServiceDeclarations(String name) + throws IOException { + + Set classSet = new HashSet(); + + for (ClassLoader classLoader : registeredClassLoaders) { + getServiceClasses(classLoader, name, classSet, true); + } + return classSet; + } + + /** + * Get all service declarations for this interface + * + * @param serviceInterface + * @return set of service declarations + * @throws IOException + */ + public Set getServiceDeclarations( + Class serviceInterface) throws IOException { + + return getServiceDeclarations(serviceInterface.getName()); + } + + /** + * Load one service implementation class for this interface + * + * @param serviceInterface + * @return service implementation class + * @throws IOException + * @throws ClassNotFoundException + */ + public Class loadFirstServiceClass(Class serviceInterface) + throws IOException, ClassNotFoundException { + + Set classSet = new HashSet(); + + for (ClassLoader classLoader : registeredClassLoaders) { + getServiceClasses(classLoader, serviceInterface.getName(), + classSet, false); + if (classSet.size() > 0) + break; + } + if (classSet.size() > 0) + return classSet.iterator().next().loadClass(); + else + return null; + + } + + /** + * Returns a unique list of resource URLs of name META-INF/services/ + * Each URL is associated with the first ClassLoader that it was visible + * from + * + * @param name Name of resource + * @return Table of URLs with associated ClassLoaders + * @throws IOException + */ + public Hashtable> getServiceResources( + final String name) throws IOException { + + Hashtable> resourceTable = new Hashtable>(); + + HashSet allURLs = new HashSet(); + for (final ClassLoader classLoader : registeredClassLoaders) { + HashSet urls = new HashSet(); + resourceTable.put(classLoader, urls); + boolean debug = logger.isLoggable(Level.FINE); + if (debug) { + logger.fine("Discovering service resources using class loader " + + classLoader); + } + // Allow privileged access to read META-INF/services/*. Add FilePermission to added to security policy file. + ArrayList urlList; + try { + // FIXME J2 Security - promote this to callers of this method + urlList = AccessController + .doPrivileged(new PrivilegedExceptionAction>() { + public ArrayList run() throws IOException { + return Collections.list(classLoader + .getResources("META-INF/services/" + + name)); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + + for (URL url : urlList) { + if (allURLs.contains(url)) + continue; + urls.add(url); + } + allURLs.addAll(urls); + } + return resourceTable; + } + + /** + * Parse a service declaration in the form class;attr=value,attr=value and + * return a map of attributes + * + * @param declaration + * @return a map of attributes + */ + private Map parseServiceDeclaration(String declaration) { + Map attributes = new HashMap(); + int index = declaration.indexOf(';'); + if (index != -1) { + attributes.put("class", declaration.substring(0, index).trim()); + declaration = declaration.substring(index); + } else { + int j = declaration.indexOf('='); + if (j == -1) { + attributes.put("class", declaration.trim()); + return attributes; + } else { + declaration = ";" + declaration; + } + } + StringTokenizer tokens = new StringTokenizer(declaration); + for (; tokens.hasMoreTokens();) { + String key = tokens.nextToken("=").substring(1).trim(); + if (key == null) + break; + String value = tokens.nextToken(",").substring(1).trim(); + if (value == null) + break; + attributes.put(key, value); + } + return attributes; + } + + /** + * Load the service class whose name specified in a configuration file + * + * @param classLoader + * @param name The name of the service class + * @param classSet Populate this set with classes extends/implements the + * service class + * @throws IOException + */ + private void getServiceClasses(final ClassLoader classLoader, + final String name, Set classSet, + boolean findAllClasses) throws IOException { + + if ("org.apache.tuscany.sca.contribution.processor.PackageProcessor" + .equals(name)) { + + for (String reg : new String[] { + "org.apache.tuscany.sca.contribution.processor.impl.FolderContributionProcessor;type=application/vnd.tuscany.folder", + "org.apache.tuscany.sca.contribution.processor.impl.JarContributionProcessor;type=application/x-compressed", + "org.apache.tuscany.sca.contribution.processor.impl.DexContributionProcessor;type=application/x-dex" }) { + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + } + + } else if ("org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor" + .equals(name)) { + + for (String reg : new String[] { + "org.apache.tuscany.sca.implementation.java.xml.JavaImplementationProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#implementation.java,model=org.apache.tuscany.sca.implementation.java.JavaImplementation" + }) { + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + } + + } else if ("org.apache.tuscany.sca.provider.PolicyProviderFactory" + .equals(name)) { + + for (String reg : new String[] { + "org.apache.tuscany.sca.policy.logging.jdk.JDKLoggingPolicyProviderFactory;model=org.apache.tuscany.sca.policy.logging.jdk.JDKLoggingPolicy" + }) { + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + } + + } else if ("org.apache.tuscany.sca.provider.BindingProviderFactory" + .equals(name)) { + + for (String reg : new String[] { + "org.apache.tuscany.sca.binding.sca.impl.RuntimeSCABindingProviderFactory;model=org.apache.tuscany.sca.assembly.SCABinding" + + }) { + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + } + + } else if ("org.apache.tuscany.sca.contribution.resolver.ModelResolver" + .equals(name)) { + + for (String reg : new String[] { + "org.apache.tuscany.sca.contribution.resource.impl.ArtifactModelResolver;model=org.apache.tuscany.sca.contribution.Artifact", + "org.apache.tuscany.sca.assembly.xml.CompositeModelResolver;model=org.apache.tuscany.sca.assembly.Composite", + "org.apache.tuscany.sca.assembly.xml.ComponentTypeModelResolver;model=org.apache.tuscany.sca.assembly.ComponentType", + "org.apache.tuscany.sca.assembly.xml.ConstrainingTypeModelResolver;model=org.apache.tuscany.sca.assembly.ConstrainingType", + "org.apache.tuscany.sca.contribution.java.impl.ClassReferenceModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ClassReference", + "org.apache.tuscany.sca.contribution.xml.ContributionModelResolver;model=org.apache.tuscany.sca.contribution.Contribution" + /*"org.apache.tuscany.sca.contribution.java.impl.ClassReferenceModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ClassReference", + "org.apache.tuscany.sca.contribution.resolver.impl.ResourceReferenceModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ResourceReference", + "org.apache.tuscany.sca.assembly.xml.ComponentTypeModelResolver;model=org.apache.tuscany.sca.assembly.ComponentType", + "org.apache.tuscany.sca.assembly.xml.ConstrainingTypeModelResolver;model=org.apache.tuscany.sca.assembly.ConstrainingType", + "org.apache.tuscany.sca.assembly.xml.CompositeModelResolver;model=org.apache.tuscany.sca.assembly.Composite", + "org.apache.tuscany.sca.interfacedef.wsdl.xml.XSDModelResolver;model=org.apache.tuscany.sca.interfacedef.wsdl.XSDefinition", + "org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLModelResolver;model=org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition", + "org.apache.tuscany.sca.contribution.osgi.impl.OSGiBundleReferenceModelResolver;model=org.apache.tuscany.sca.contribution.osgi.BundleReference"*/ + }) { + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + } + + } else if ("org.apache.tuscany.sca.core.ModuleActivator" + .equals(name)) { + + for (String reg : new String[] { + "org.apache.tuscany.sca.core.databinding.module.DataBindingModuleActivator", + "org.apache.tuscany.sca.implementation.java.module.JavaRuntimeModuleActivator" + /* + * "org.apache.tuscany.sca.contribution.java.impl.ClassReferenceModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ClassReference", + * "org.apache.tuscany.sca.contribution.resolver.impl.ResourceReferenceModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ResourceReference", + * "org.apache.tuscany.sca.assembly.xml.ComponentTypeModelResolver;model=org.apache.tuscany.sca.assembly.ComponentType", + * "org.apache.tuscany.sca.assembly.xml.ConstrainingTypeModelResolver;model=org.apache.tuscany.sca.assembly.ConstrainingType", + * "org.apache.tuscany.sca.assembly.xml.CompositeModelResolver;model=org.apache.tuscany.sca.assembly.Composite", + * "org.apache.tuscany.sca.interfacedef.wsdl.xml.XSDModelResolver;model=org.apache.tuscany.sca.interfacedef.wsdl.XSDefinition", + * "org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLModelResolver;model=org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition", + * "org.apache.tuscany.sca.contribution.osgi.impl.OSGiBundleReferenceModelResolver;model=org.apache.tuscany.sca.contribution.osgi.BundleReference" + */ + }) { + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + } + + } else { + boolean debug = logger.isLoggable(Level.FINE); + if (debug) { + logger.fine("Discovering service providers using class loader " + + classLoader); + } + // Allow privileged access to read META-INF/services/*. Add FilePermission to added to + // security policy file. + ArrayList urlList; + try { + urlList = AccessController + .doPrivileged(new PrivilegedExceptionAction>() { + public ArrayList run() throws IOException { + return Collections.list(classLoader + .getResources("META-INF/services/" + + name)); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + + for (final URL url : urlList) { + if (debug) { + logger.fine("Reading service provider file: " + + url.toExternalForm()); + } + + // Allow privileged access to open URL stream. Add FilePermission to added to security + // policy file. + InputStream is; + try { + is = AccessController + .doPrivileged(new PrivilegedExceptionAction() { + public InputStream run() throws IOException { + return url.openStream(); + } + }); + } catch (PrivilegedActionException e) { + throw (IOException) e.getException(); + } + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(is)); + while (true) { + String line = reader.readLine(); + if (line == null) + break; + line = line.trim(); + if (!line.startsWith("#") && !"".equals(line)) { + String reg = line.trim(); + if (debug) { + logger.fine("Registering service provider: " + + reg); + } + + Map attributes = parseServiceDeclaration(reg); + String className = attributes.get("class"); + ServiceDeclaration serviceClass = new ServiceDeclaration( + className, classLoader, attributes); + classSet.add(serviceClass); + + if (!findAllClasses) + break; + } + } + } finally { + if (reader != null) + reader.close(); + if (is != null) { + try { + is.close(); + } catch (IOException ioe) { + } + } + } + if (!findAllClasses && classSet.size() > 0) + break; + } + + } + } + +} diff --git a/branches/sca-android/host-android/.classpath b/branches/sca-android/host-android/.classpath new file mode 100644 index 0000000000..a5b6e1a5ac --- /dev/null +++ b/branches/sca-android/host-android/.classpath @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/host-android/.project b/branches/sca-android/host-android/.project new file mode 100644 index 0000000000..7f49c40c5f --- /dev/null +++ b/branches/sca-android/host-android/.project @@ -0,0 +1,44 @@ + + tuscany-host-embedded + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly-xml + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-core-spi + tuscany-sca-api + tuscany-contribution + tuscany-contribution-namespace + tuscany-contribution-java + tuscany-assembly-xsd + tuscany-binding-sca + tuscany-core + tuscany-interface-java + tuscany-contribution-impl + tuscany-contribution-xml + tuscany-contribution-resource + tuscany-node + tuscany-domain + tuscany-domain-api + tuscany-node-api + tuscany-binding-sca-xml + tuscany-core-databinding + tuscany-databinding + tuscany-databinding-jaxb + tuscany-interface-java-xml + tuscany-interface-java-jaxws + tuscany-definitions-xml + tuscany-policy-xml + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/host-android/DISCLAIMER b/branches/sca-android/host-android/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/host-android/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/host-android/LICENSE b/branches/sca-android/host-android/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/host-android/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/branches/sca-android/host-android/NOTICE b/branches/sca-android/host-android/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/host-android/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/host-android/pom.xml b/branches/sca-android/host-android/pom.xml new file mode 100644 index 0000000000..224bd104c1 --- /dev/null +++ b/branches/sca-android/host-android/pom.xml @@ -0,0 +1,106 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-host-embedded + Apache Tuscany SCA Embedded Host + + + + org.apache.tuscany.sca + tuscany-extensibility + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-core + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-definitions + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-definitions-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-assembly-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-binding-sca + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-binding-sca-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-impl + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-policy-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-node-api + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-core-databinding + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-assembly-xsd + 2.0-incubating-SNAPSHOT + runtime + + + + diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java new file mode 100644 index 0000000000..b45b418ccf --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java @@ -0,0 +1,338 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.host.embedded; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Constructor; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.tuscany.sca.android.ContextRegistry; +import org.apache.tuscany.sca.android.DexURLStreamHandlerFactory; +import org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +import android.content.Context; + +/** + * A handle to an SCA domain. + * + * @version $Rev: 628057 $ $Date: 2008-02-15 05:15:58 -0800 (Fri, 15 Feb 2008) $ + */ +public abstract class SCADomain { + + final static String LOCAL_DOMAIN_URI = "http://localhost"; + + /** + * Static variable to hold the most recent instance of SCADomain + */ + // TODO: Temporary support for SCADomain.connect() API + protected static SCADomain theDomain; + + static { + URL.setURLStreamHandlerFactory(new DexURLStreamHandlerFactory()); + } + + private Context context; + + public SCADomain() {} + + public SCADomain(Context context) { + this.context = context; + ContextRegistry.registerContext(context); + + } + + public Context getContext() { + return context; + } + + /** + * Returns a new instance of a local SCA domain. + * + * @return + */ + public static SCADomain newInstance(Context context) { + return createNewInstance(context, LOCAL_DOMAIN_URI, null); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composite will be included in the SCA domain. + * + * @param composite the deployable composite to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(Context context, String composite) { + return createNewInstance(context, LOCAL_DOMAIN_URI, "dex://" + context.getPackageName() + "/raw/", composite); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composites will be included in the SCA domain. + * + * @param domainURI the URI of the SCA domain + * @param contributionLocation the location of an SCA contribution + * @param composites the deployable composites to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(Context context, String domainURI, String contributionLocation, String... composites) { + return createNewInstance(context, domainURI, contributionLocation, composites); + } + + /** + * Returns a new instance of a local SCA domain. + * + * @return + */ + public static SCADomain newInstance() { + return createNewInstance(LOCAL_DOMAIN_URI, null); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composite will be included in the SCA domain. + * + * @param composite the deployable composite to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(String composite) { + return createNewInstance(LOCAL_DOMAIN_URI, "/", composite); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composites will be included in the SCA domain. + * + * @param domainURI the URI of the SCA domain + * @param contributionLocation the location of an SCA contribution + * @param composites the deployable composites to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(String domainURI, String contributionLocation, String... composites) { + return createNewInstance(domainURI, contributionLocation, composites); + } + + /** + * Removes the specified local SCA Domain instance + * + * @param domainInstance the instance to be removed + */ + // FIXME: Adding this as temporary support for the "connect" API + public static void removeInstance(SCADomain domainInstance) { + theDomain = null; + } + + /** + * Returns an SCADomain representing a remote SCA domain. + * + * @param domainURI the URI of the SCA domain + * @return + */ + // FIXME : this is a temporary implementation to get the capability working + public static SCADomain connect(String domainURI) { + return theDomain; + } + + /** + * Close the SCA domain. + */ + public void close() { + // TODO: temporary to support initial SCADomain.connect capability + SCADomain.removeInstance(this); + + if (context != null) { + ContextRegistry.unregisterContext(context); + } + + } + + /** + * Returns the URI of the SCA Domain. + * + * @return the URI of the SCA Domain + */ + public abstract String getURI(); + + /** + * Cast a type-safe reference to a CallableReference. Converts a type-safe + * reference to an equivalent CallableReference; if the target refers to a + * service then a ServiceReference will be returned, if the target refers to + * a callback then a CallableReference will be returned. + * + * @param target a reference proxy provided by the SCA runtime + * @param the Java type of the business interface for the reference + * @param the type of reference to be returned + * @return a CallableReference equivalent for the proxy + * @throws IllegalArgumentException if the supplied instance is not a + * reference supplied by the SCA runtime + */ + public abstract > R cast(B target) throws IllegalArgumentException; + + /** + * Returns a proxy for a service provided by a component in the SCA domain. + * + * @param businessInterface the interface that will be used to invoke the + * service + * @param serviceName the name of the service + * @param the Java type of the business interface for the service + * @return an object that implements the business interface + */ + public abstract B getService(Class businessInterface, String serviceName); + + /** + * Returns a ServiceReference for a service provided by a component in the + * SCA domain. + * + * @param businessInterface the interface that will be used to invoke the + * service + * @param serviceName the name of the service + * @param the Java type of the business interface for the service + * @return a ServiceReference for the designated service + */ + public abstract ServiceReference getServiceReference(Class businessInterface, String referenceName); + + /** + * Read the service name from a configuration file + * + * @param classLoader + * @param name The name of the service class + * @return A class name which extends/implements the service class + * @throws IOException + */ + private static String getServiceName(ClassLoader classLoader, String name) throws IOException { + InputStream is = classLoader.getResourceAsStream("META-INF/services/" + name); + if (is == null) { + return null; + } + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(is)); + while (true) { + String line = reader.readLine(); + if (line == null) { + break; + } else if (!line.startsWith("#")) { + return line.trim(); + } + } + } finally { + if (reader != null) { + reader.close(); + } + } + return null; + } + + static SCADomain createNewInstance(String domainURI, String contributionLocation, String... composites) { + return createNewInstance(null, domainURI, contributionLocation, composites); + } + + /** + * Returns an SCADomain instance. If the system property + * "org.apache.tuscany.sca.host.embedded.SCADomain" is set, its value is used as + * the name of the implementation class. Otherwise, if the resource + * "META-INF/services/org.apache.tuscany.sca.host.embedded.SCADomain" can be + * loaded from the supplied classloader. Otherwise, it will use + * "org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain" as the default. + * The named class is loaded from the supplied classloader. + * + * @param classLoader + * @param domainURI + * @param contributionLocation + * @param composites + * @return + */ + static SCADomain createNewInstance(Context context, String domainURI, String contributionLocation, String... composites) { + + SCADomain domain = null; + + try { + // Determine the runtime and application classloader + final ClassLoader runtimeClassLoader = SCADomain.class.getClassLoader(); + final ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); + + // Discover the SCADomain implementation + final String name = SCADomain.class.getName(); + String className = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(name); + } + }); + + if (className == null) { + className = getServiceName(runtimeClassLoader, name); + } + + if (className == null) { + + // Create a default SCA domain implementation + domain = + new DefaultSCADomain(context, + runtimeClassLoader, + applicationClassLoader, + domainURI, + contributionLocation, + composites); + } else { + + // Create an instance of the discovered SCA domain implementation + Class cls = Class.forName(className, true, runtimeClassLoader); + Constructor constructor = null; + try { + constructor = cls.getConstructor(ClassLoader.class, ClassLoader.class, + String.class, String.class, String[].class); + } catch (NoSuchMethodException e) {} + if (constructor != null) { + domain = (SCADomain)constructor.newInstance(runtimeClassLoader, + applicationClassLoader, + domainURI, + contributionLocation, + composites); + } else { + + constructor = cls.getConstructor(ClassLoader.class, String.class); + domain = (SCADomain)constructor.newInstance(runtimeClassLoader, domainURI); + } + } + + // FIXME: temporary support for connect() API + theDomain = domain; + + return domain; + + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public ComponentManager getComponentManager() { + return null; + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java new file mode 100644 index 0000000000..1bb0662118 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded; + +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + +public class SCADomainBean extends SCADomain { + + private SCADomain instance; + + private String uri = LOCAL_DOMAIN_URI; + private String location = "/"; + private String[] composites; + + /** + * Constructs a new SCA domain + */ + public SCADomainBean() {} + + @Override + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public void setContributionLocation(String contributionLocation) { + this.location = contributionLocation; + } + + public String getContributionLocation() { + return location; + } + + public void setDeployableComposite(String composite) { + setDeployableComposites(composite); + } + + public void setDeployableComposites(String... composites) { + this.composites = composites; + } + + public String[] getDeployableComposites() { + return composites; + } + + @SuppressWarnings("unchecked") + @Override + public > R cast(B target) throws IllegalArgumentException { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + Object result = instance.cast(target); + return (R) result; + } + + @Override + public void close() { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + instance.close(); + instance = null; + } + + @Override + public B getService(Class businessInterface, String serviceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getService(businessInterface, serviceName); + } + + @Override + public ServiceReference getServiceReference(Class businessInterface, String referenceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getServiceReference(businessInterface, referenceName); + } + + @Override + protected void finalize() throws Throwable { + + // Make sure that the SCA domain is closed + if (instance != null) { + instance.close(); + instance = null; + } + } + + @Override + public ComponentManager getComponentManager() { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getComponentManager(); + } +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java new file mode 100644 index 0000000000..a1f272cb06 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.host.embedded; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * A helper class that can be used to run an SCA JUnit test case. The test case will run in an isolated class loader. + * + * @version $Rev: 637634 $ $Date: 2008-03-16 12:59:48 -0700 (Sun, 16 Mar 2008) $ + */ +public class SCATestCaseRunner { + + private ClassLoader classLoader; + private Class testSuiteClass; + private Object testSuite; + private Class testResultClass; + private Class testCaseClass; + private Object testCase; + + private Class beforeAnnotation; + private Class beforeClassAnnotation; + private Class afterAnnotation; + private Class afterClassAnnotation; + private Class junit4AdapterClass; + private Class junit3TestCaseClass; + + /** + * Constructs a new TestCase runner. + * + * @param testClass + */ + public SCATestCaseRunner(Class testClass) { + try { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + classLoader = testClass.getClassLoader(); + if (classLoader instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader)classLoader).getURLs(); + classLoader = new URLClassLoader(urls, classLoader.getParent()); + } else if (classLoader == tccl || classLoader.getParent() == tccl) { + classLoader = new URLClassLoader(new URL[0], classLoader); + } else { + classLoader = tccl; + } + + try { + Thread.currentThread().setContextClassLoader(classLoader); + + testCaseClass = Class.forName(testClass.getName(), true, classLoader); + testCase = testCaseClass.newInstance(); + ClassLoader testClassLoader = testCaseClass.getClassLoader(); + + junit3TestCaseClass = Class.forName("junit.framework.TestCase", true, testClassLoader); + + testSuiteClass = Class.forName("junit.framework.TestSuite", true, testClassLoader); + Constructor testSuiteConstructor = testSuiteClass.getConstructor(Class.class); + testSuite = testSuiteConstructor.newInstance(testCaseClass); + + testResultClass = Class.forName("junit.framework.TestResult", true, testClassLoader); + + try { + beforeAnnotation = Class.forName("org.junit.Before", true, testClassLoader); + afterAnnotation = Class.forName("org.junit.After", true, testClassLoader); + beforeClassAnnotation = Class.forName("org.junit.BeforeClass", true, testClassLoader); + afterClassAnnotation = Class.forName("org.junit.AfterClass", true, testClassLoader); + junit4AdapterClass = Class.forName("junit.framework.JUnit4TestAdapter", true, testClassLoader); + } catch (Exception e) { + // Unexpected + throw new AssertionError(e); + } + + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Run the test case + */ + public void run() { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + + if (junit3TestCaseClass.isAssignableFrom(testCaseClass)) { + Object testResult = testResultClass.newInstance(); + Method runMethod = testSuiteClass.getMethod("run", testResultClass); + runMethod.invoke(testSuite, testResult); + } else { + Object junit4Adapter = junit4AdapterClass.getConstructor(Class.class).newInstance(testCaseClass); + Object testResult = testResultClass.newInstance(); + Method runMethod = junit4AdapterClass.getMethod("run", testResultClass); + runMethod.invoke(junit4Adapter, testResult); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + + /** + * Invoke the setUp method + */ + public void setUp() { + execute("setUp"); + } + + /** + * Invoke the before methods + */ + public void before() { + execute(beforeAnnotation); + } + + /** + * Invoke the beforeClass methods + */ + public void beforeClass() { + execute(beforeClassAnnotation); + } + + /** + * Invoke the tearDown method + */ + public void tearDown() { + execute("tearDown"); + } + + /** + * Invoke the after methods + */ + public void after() { + execute(afterAnnotation); + } + + /** + * Invoke the afterClass methods + */ + public void afterClass() { + execute(afterClassAnnotation); + } + + /** + * Invoke the specified test method. + */ + public void run(String methodName) { + execute(methodName); + } + + /** + * Invoke the methods annotated with the specified annotation. + */ + private void execute(Class annotationClass) { + if (annotationClass == null) { + throw new RuntimeException(new NoSuchMethodException()); + } + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + + for (Method method : testCaseClass.getDeclaredMethods()) { + for (Annotation annotation : method.getAnnotations()) { + if (annotation.annotationType() == annotationClass) { + method.invoke(testCase); + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + + /** + * Invoke the specified method + */ + private void execute(String methodName) { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + Method setUpMethod = testCaseClass.getDeclaredMethod(methodName); + setUpMethod.setAccessible(true); + setUpMethod.invoke(testCase); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java new file mode 100644 index 0000000000..acd0fb91e4 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; + +public class ComponentManagerImpl implements ComponentManager { + + protected List listeners = new CopyOnWriteArrayList(); + protected EmbeddedSCADomain domain; + + public ComponentManagerImpl(EmbeddedSCADomain domain) { + this.domain = domain; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Set getComponentNames() { + Set names = new HashSet(); + for (Composite composite: domain.getDomainComposite().getIncludes()) { + for (Component component: composite.getComponents()) { + names.add(component.getName()); + } + } + return names; + } + + public Component getComponent(String componentName) { + for (Composite composite: domain.getDomainComposite().getIncludes()) { + for (Component component: composite.getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + return null; + } + + public void startComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + domain.getCompositeActivator().start(component); + notifyComponentStarted(componentName); + } + + public void stopComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + domain.getCompositeActivator().stop(component); + notifyComponentStopped(componentName); + } + + public void notifyComponentStarted(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(String componentName) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)getComponent(componentName); + return runtimeComponent.isStarted(); + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java new file mode 100644 index 0000000000..5f73dbe008 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java @@ -0,0 +1,584 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.host.embedded.impl; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionException; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +import android.content.Context; + +/** + * A default SCA domain facade implementation. + * + * @version $Rev: 637139 $ $Date: 2008-03-14 09:02:49 -0700 (Fri, 14 Mar 2008) $ + */ +public class DefaultSCADomain extends SCADomain { + + private String uri; + private String[] composites; + private Composite domainComposite; + private List contributions; + private Map components; + private ReallySmallRuntime runtime; + private ComponentManager componentManager; + private ClassLoader runtimeClassLoader; + private ClassLoader applicationClassLoader; + private String domainURI; + private String contributionLocation; + + /** + * Constructs a new domain facade. + * + * @param domainURI + * @param contributionLocation + * @param composites + */ + public DefaultSCADomain(ClassLoader runtimeClassLoader, + ClassLoader applicationClassLoader, + String domainURI, + String contributionLocation, + String... composites) { + this.uri = domainURI; + this.composites = composites; + this.runtimeClassLoader = runtimeClassLoader; + this.applicationClassLoader = applicationClassLoader; + this.domainURI = domainURI; + this.contributionLocation = contributionLocation; + this.composites = composites; + + init(); + + } + + /** + * Constructs a new domain facade. + * + * @param domainURI + * @param contributionLocation + * @param composites + */ + public DefaultSCADomain(Context context, + ClassLoader runtimeClassLoader, + ClassLoader applicationClassLoader, + String domainURI, + String contributionLocation, + String... composites) { + super(context); + this.uri = domainURI; + this.composites = composites; + this.runtimeClassLoader = runtimeClassLoader; + this.applicationClassLoader = applicationClassLoader; + this.domainURI = domainURI; + this.contributionLocation = contributionLocation; + this.composites = composites; + + init(); + + } + + public void init() { + contributions = new ArrayList(); + components = new HashMap(); + runtime = new ReallySmallRuntime(runtimeClassLoader); + try { + runtime.start(); + + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + + // Contribute the given contribution to an in-memory repository + ContributionService contributionService = runtime.getContributionService(); + URL contributionURL; + try { + contributionURL = getContributionLocation(applicationClassLoader, contributionLocation, this.composites); + /* if (contributionURL != null) { + // Make sure the URL is correctly encoded (for example, escape the space characters) + contributionURL = contributionURL.toURI().toURL(); + }*/ + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + + try { + addContribution(contributionService, contributionURL); + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } + + /* try { + String scheme = contributionURL.toURI().getScheme(); + if (scheme == null || scheme.equalsIgnoreCase("file")) { + File contributionFile = new File(contributionURL.toURI()); + if (contributionFile.isDirectory()) { + String[] contributions = contributionFile.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + } + }); + if (contributions != null && contributions.length > 0 && contributions.length == contributionFile.list().length) { + for (String contribution : contributions) { + addContribution(contributionService, new File(contributionFile, contribution).toURI().toURL()); + } + } else { + addContribution(contributionService, contributionURL); + } + } else { + addContribution(contributionService, contributionURL); + } + } else { + addContribution(contributionService, contributionURL); + } + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } catch (URISyntaxException e) { + throw new ServiceRuntimeException(e); + }*/ + + // Create an in-memory domain level composite + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + domainComposite = assemblyFactory.createComposite(); + domainComposite.setName(new QName(Constants.SCA10_NS, "domain")); + domainComposite.setURI(domainURI); + + //when the deployable composites were specified when initializing the runtime + if (composites != null && composites.length > 0 && composites[0].length() > 0) { + // Include all specified deployable composites in the SCA domain + Map compositeArtifacts = new HashMap(); + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + compositeArtifacts.put(artifact.getURI(), (Composite)artifact.getModel()); + } + } + } + for (String compositePath : composites) { + Composite composite = compositeArtifacts.get(compositePath); + if (composite == null) { + throw new ServiceRuntimeException("Composite not found: " + compositePath); + } + domainComposite.getIncludes().add(composite); + } + } else { + // in this case, a sca-contribution.xml should have been specified + for (Contribution contribution : contributions) { + for (Composite composite : contribution.getDeployables()) { + domainComposite.getIncludes().add(composite); + } + } + } + + //update the runtime for all SCA Definitions processed from the contribution.. + //so that the policyset determination done during 'build' has the all the defined + //intents and policysets + //runtime.updateSCADefinitions(null); + + // Build the SCA composites + for (Composite composite : domainComposite.getIncludes()) { + try { + runtime.buildComposite(composite); + } catch (CompositeBuilderException e) { + throw new ServiceRuntimeException(e); + } + } + + // Activate and start composites + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + compositeActivator.setDomainComposite(domainComposite); + for (Composite composite : domainComposite.getIncludes()) { + try { + compositeActivator.activate(composite); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + for (Composite composite : domainComposite.getIncludes()) { + try { + for (Component component : composite.getComponents()) { + compositeActivator.start(component); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + + // Index the top level components + for (Composite composite : domainComposite.getIncludes()) { + for (Component component : composite.getComponents()) { + components.put(component.getName(), component); + } + } + + this.componentManager = new DefaultSCADomainComponentManager(this); + + // For debugging purposes, print the composites +// ExtensionPointRegistry extensionPoints = runtime.getExtensionPointRegistry(); +// StAXArtifactProcessorExtensionPoint artifactProcessors = extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); +// StAXArtifactProcessor processor = artifactProcessors.getProcessor(Composite.class); +// for (Composite composite : domainComposite.getIncludes()) { +// try { +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +// outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); +// processor.write(composite, outputFactory.createXMLStreamWriter(bos)); +// Document document = +// DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(bos +// .toByteArray())); +// OutputFormat format = new OutputFormat(); +// format.setIndenting(true); +// format.setIndent(2); +// XMLSerializer serializer = new XMLSerializer(System.out, format); +// serializer.serialize(document); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + } + + protected void addContribution(ContributionService contributionService, URL contributionURL) throws IOException { + try { + String contributionURI = FileHelper.getName(contributionURL.getPath()); + if (contributionURI == null || contributionURI.length() == 0) { + contributionURI = contributionURL.toString(); + } + contributions.add(contributionService.contribute(contributionURI, contributionURL, false)); + } catch (ContributionException e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public void close() { + + super.close(); + + // Stop and deactivate composites + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + for (Composite composite : domainComposite.getIncludes()) { + try { + for (Component component : composite.getComponents()) { + compositeActivator.stop(component); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + for (Composite composite : domainComposite.getIncludes()) { + try { + compositeActivator.deactivate(composite); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + + // Remove the contribution from the in-memory repository + ContributionService contributionService = runtime.getContributionService(); + for (Contribution contribution : contributions) { + try { + contributionService.remove(contribution.getURI()); + } catch (ContributionException e) { + throw new ServiceRuntimeException(e); + } + } + + // Stop the runtime + try { + runtime.stop(); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Determine the location of a contribution, given a contribution path and a + * list of composites. + * + * @param contributionPath + * @param composites + * @param classLoader + * @return + * @throws MalformedURLException + */ + protected URL getContributionLocation(ClassLoader classLoader, String contributionPath, String[] composites) + throws MalformedURLException { + + return new URL(contributionPath); + + } + + @Override + @SuppressWarnings("unchecked") + public > R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public B getService(Class businessInterface, String serviceName) { + ServiceReference serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private ServiceReference createServiceReference(Class businessInterface, String targetURI) { + try { + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + Composite composite = assemblyFactory.createComposite(); + composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default")); + RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent(); + component.setName("default"); + component.setURI("default"); + runtime.getCompositeActivator().configureComponentContext(component); + composite.getComponents().add(component); + RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference(); + reference.setName("default"); + ModelFactoryExtensionPoint factories = + runtime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); + reference.setInterfaceContract(interfaceContract); + component.getReferences().add(reference); + reference.setComponent(component); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + SCABinding binding = scaBindingFactory.createSCABinding(); + binding.setURI(targetURI); + reference.getBindings().add(binding); + return new ServiceReferenceImpl(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public ServiceReference getServiceReference(Class businessInterface, String name) { + + // Extract the component name + String componentName; + String serviceName; + int i = name.indexOf('/'); + if (i != -1) { + componentName = name.substring(0, i); + serviceName = name.substring(i + 1); + + } else { + componentName = name; + serviceName = null; + } + + // Lookup the component in the domain + Component component = components.get(componentName); + if (component == null) { + // The component is not local in the partition, try to create a remote service ref + return createServiceReference(businessInterface, name); + } + RuntimeComponentContext componentContext = null; + + // If the component is a composite, then we need to find the + // non-composite component that provides the requested service + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + if (serviceName == null || serviceName.equals(componentService.getName())) { + CompositeService compositeService = (CompositeService)componentService.getService(); + if (compositeService != null) { + if (serviceName != null) { + serviceName = "$promoted$." + serviceName; + } + componentContext = + ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext(); + return componentContext.createSelfReference(businessInterface, compositeService + .getPromotedService()); + } + break; + } + } + // No matching service is found + throw new ServiceRuntimeException("Composite service not found: " + name); + } else { + componentContext = ((RuntimeComponent)component).getComponentContext(); + if (serviceName != null) { + return componentContext.createSelfReference(businessInterface, serviceName); + } else { + return componentContext.createSelfReference(businessInterface); + } + } + + } + + @Override + public String getURI() { + return uri; + } + + @Override + public ComponentManager getComponentManager() { + return componentManager; + } + + public Set getComponentNames() { + Set componentNames = new HashSet(); + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + for (Component component : ((Composite)artifact.getModel()).getComponents()) { + componentNames.add(component.getName()); + } + } + } + } + return componentNames; + } + + public Component getComponent(String componentName) { + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + for (Component component : ((Composite)artifact.getModel()).getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + } + } + return null; + } + + public void startComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + compositeActivator.start(component); + } + + public void stopComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + compositeActivator.stop(component); + } +} + +class DefaultSCADomainComponentManager implements ComponentManager { + + protected DefaultSCADomain scaDomain; + protected List listeners = new CopyOnWriteArrayList(); + + public DefaultSCADomainComponentManager(DefaultSCADomain scaDomain) { + this.scaDomain = scaDomain; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Set getComponentNames() { + return scaDomain.getComponentNames(); + } + + public Component getComponent(String componentName) { + return scaDomain.getComponent(componentName); + } + + public void startComponent(String componentName) throws ActivationException { + scaDomain.startComponent(componentName); + } + + public void stopComponent(String componentName) throws ActivationException { + scaDomain.stopComponent(componentName); + } + + public void notifyComponentStarted(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(String componentName) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)getComponent(componentName); + return runtimeComponent.isStarted(); + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java new file mode 100644 index 0000000000..647443a88e --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java @@ -0,0 +1,234 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * An SCA domain facade implementation. + * + * @version $Rev: 638890 $ $Date: 2008-03-19 08:52:30 -0700 (Wed, 19 Mar 2008) $ + */ +public class EmbeddedSCADomain extends SCADomain { + + private String uri; + private Composite domainComposite; + private ReallySmallRuntime runtime; + private ComponentManagerImpl componentManager = new ComponentManagerImpl(this); + + /** + * Constructs a new domain facade. + * + * @param runtimeClassLoader + * @param domainURI + */ + public EmbeddedSCADomain(ClassLoader runtimeClassLoader, + String domainURI) { + this.uri = domainURI; + + // Create a runtime + runtime = new ReallySmallRuntime(null/*runtimeClassLoader*/); + } + + public void start() throws ActivationException { + + // Start the runtime + runtime.start(); + + // Create an in-memory domain level composite + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + domainComposite = assemblyFactory.createComposite(); + domainComposite.setName(new QName(Constants.SCA10_NS, "domain")); + domainComposite.setURI(uri); + + getCompositeActivator().setDomainComposite(domainComposite); + + } + + public void stop() throws ActivationException { + + // Stop the runtime + runtime.stop(); + + // Cleanup + domainComposite = null; + } + + public void buildComposite(Composite composite) throws CompositeBuilderException { + runtime.buildComposite(composite); + } + + public ContributionService getContributionService() { + return runtime.getContributionService(); + } + + public CompositeBuilder getCompositeBuilder() { + return runtime.getCompositeBuilder(); + } + + public CompositeActivator getCompositeActivator() { + return runtime.getCompositeActivator(); + } + + public Composite getDomainComposite() { + return domainComposite; + } + + @Override + public ComponentManager getComponentManager() { + return componentManager; + } + + @Override + public void close() { + super.close(); + } + + @Override + public > R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public B getService(Class businessInterface, String serviceName) { + ServiceReference serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private ServiceReference createServiceReference(Class businessInterface, String targetURI) { + try { + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + Composite composite = assemblyFactory.createComposite(); + composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default")); + RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent(); + component.setName("default"); + component.setURI("default"); + runtime.getCompositeActivator().configureComponentContext(component); + composite.getComponents().add(component); + RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference(); + reference.setName("default"); + ModelFactoryExtensionPoint factories = + runtime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); + reference.setInterfaceContract(interfaceContract); + component.getReferences().add(reference); + reference.setComponent(component); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + SCABinding binding = scaBindingFactory.createSCABinding(); + binding.setURI(targetURI); + reference.getBindings().add(binding); + return new ServiceReferenceImpl(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + @Override + public ServiceReference getServiceReference(Class businessInterface, String name) { + + // Extract the component name + String componentName; + String serviceName; + int i = name.indexOf('/'); + if (i != -1) { + componentName = name.substring(0, i); + serviceName = name.substring(i + 1); + + } else { + componentName = name; + serviceName = null; + } + + // Lookup the component in the domain + Component component = componentManager.getComponent(componentName); + if (component == null) { + // The component is not local in the partition, try to create a remote service ref + return createServiceReference(businessInterface, name); + } + RuntimeComponentContext componentContext = null; + + // If the component is a composite, then we need to find the + // non-composite component that provides the requested service + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + if (serviceName == null || serviceName.equals(componentService.getName())) { + CompositeService compositeService = (CompositeService)componentService.getService(); + if (compositeService != null) { + if (serviceName != null) { + serviceName = "$promoted$." + serviceName; + } + componentContext = + ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext(); + return componentContext.createSelfReference(businessInterface, compositeService + .getPromotedService()); + } + break; + } + } + // No matching service is found + throw new ServiceRuntimeException("Composite service not found: " + name); + } else { + componentContext = ((RuntimeComponent)component).getComponentContext(); + if (serviceName != null) { + return componentContext.createSelfReference(businessInterface, serviceName); + } else { + return componentContext.createSelfReference(businessInterface); + } + } + + } + + @Override + public String getURI() { + return uri; + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java new file mode 100644 index 0000000000..bc2edb7de9 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java @@ -0,0 +1,387 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.host.embedded.impl; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * An SCADomain that starts a Tuscany runtime supporting multiple + * SCA contribution jars. All contribution jars found in a repository + * directory will be contributed to the SCA domain. Any changes to the + * contributions in that repository will be automatically detected and + * the sca domain updated accordingly. + * + * TODO: find how to properly add/remove contributions and start/activate the doamain + * TODO: support contributions that are folders as well as jar's + * TODO: needs to restart the entire scadomain when a contribution changes + * as the domain classpath includes all the contribution jar's, would + * be nice to find a way to avoid this + * TODO: hot update requires copying contribution jars to a temp location + * to avoid the classpath lock preventing updating the contribution + * jars, would be nice to find a way to avoid that + */ +public class HotUpdatableSCADomain extends SCADomain { + private static final Logger logger = Logger.getLogger(HotUpdatableSCADomain.class.getName()); + protected String domainURI; + protected File contributionRepository; + + protected EmbeddedSCADomain scaDomain; + + protected boolean hotUpdateActive; + protected Thread hotUpdateThread; + protected int hotUpdateInterval; // milliseconds, 0 = hotupdate disabled + + protected HashMap existingContributions; // value is last modified time + protected ClassLoader originalCCL; + + protected static final String REPOSITORY_FOLDER = "sca-contributions"; + + public HotUpdatableSCADomain(String domainURI, File contributionRepository, int hotupdateInterval) { + this.domainURI = domainURI; + this.contributionRepository = contributionRepository; + this.hotUpdateInterval = hotupdateInterval; + this.originalCCL = Thread.currentThread().getContextClassLoader(); + start(); + } + + protected void start() { + try { + initEmbeddedSCADomain(); + activateHotUpdate(); + for (URL url : existingContributions.keySet()) { + File f = new File(url.toURI()); + logger.info("added contribution: " + f.getName()); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } catch (URISyntaxException e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public void close() { + try { + hotUpdateActive = false; + scaDomain.stop(); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + Thread.currentThread().setContextClassLoader(originalCCL); + super.close(); + } + + + protected SCADomain initEmbeddedSCADomain() throws ActivationException { + + URL[] contributionJars = getContributionJarURLs(contributionRepository); + + this.existingContributions = getLastModified(contributionJars); + + if (hotUpdateInterval > 0) { + contributionJars = copyContributionsToTemp(contributionJars); + } + + // Using the CCL as the parent exposes Tuscany to the contributions, want to do this? + URLClassLoader cl = new URLClassLoader(contributionJars, originalCCL); + Thread.currentThread().setContextClassLoader(cl); + + scaDomain = new EmbeddedSCADomain(cl, domainURI); + + scaDomain.start(); + + initContributions(scaDomain, cl, contributionJars); + + return scaDomain; + } + + protected URL[] getContributionJarURLs(File repositoryDir) { + + String[] jars = repositoryDir.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + }}); + + List contributionJars = new ArrayList(); + if (jars != null) { + for (String jar : jars) { + try { + contributionJars.add(new File(repositoryDir, jar).toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + return contributionJars.toArray(new URL[contributionJars.size()]); + } + + /** + * TODO: No idea what the 'correct' way to add/contribute and activate/start things to an scaDomain is + * but this seems to work. Doesn't seem to start s or s which are outside of + * a so something is missing/wrong. Also this doesn't seem to be picking up composites + * located in META-INF/deployables or specified in the sca-deployables.xml. Maybe the EmbeddedSCADomain + * and ContributionService APIs should make all this easier? + */ + protected void initContributions(EmbeddedSCADomain scaDomain, ClassLoader cl, URL[] contributionJars) { + Contribution contribution = null; + ContributionService contributionService = scaDomain.getContributionService(); + for (URL jar : contributionJars) { + InputStream is = null; + try { + is = jar.openStream(); + contribution = contributionService.contribute(jar.toString(), jar, is); + } catch (Exception e) { + System.err.println("exception adding contribution: " + jar); + e.printStackTrace(); + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } + + if (contribution != null ) { + try { + + for (Composite composite : contribution.getDeployables()) { + scaDomain.getDomainComposite().getIncludes().add(composite); + scaDomain.getCompositeBuilder().build(composite); + scaDomain.getCompositeActivator().activate(composite); + } + + for (Composite composite : contribution.getDeployables()) { + scaDomain.getCompositeActivator().start(composite); + } + + } catch (ActivationException e) { + throw new RuntimeException(e); + } catch (CompositeBuilderException e) { + throw new RuntimeException(e); + } + } + + } + + /** + * Copies Files to a temp location returning the URLs of the new temp files. + * For hot update to work need to be able to delete/update the contribution jar's + * but as they're in the classpath the URLClassLoader has an open lock on the jar's + * so you can't update them. This solution copies each contribution to a temp + * location for use on the classpath, nicer would be a ClassLoder impl that doesn't + * lock the jar's. + */ + protected URL[] copyContributionsToTemp(URL[] contributionJars) { + try { + + URL[] newURLs = new URL[contributionJars.length]; + File tempDir = new File(System.getProperty("java.io.tmpdir")); + for (int i=0; i getLastModified(URL[] contrabutions) { + try { + + HashMap contributionLastUpdates = new HashMap(); + for (URL url: contrabutions) { + File f = new File(url.toURI()); + contributionLastUpdates.put(url, new Long(f.lastModified())); + } + return contributionLastUpdates; + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + protected void activateHotUpdate() { + if (hotUpdateInterval == 0) { + return; // hotUpdateInterval of 0 disables hotupdate + } + + Runnable runable = new Runnable() { + public void run() { + logger.info("Tuscany contribution hotupdate running"); + while (hotUpdateActive) { + try { + Thread.sleep(hotUpdateInterval); + } catch (InterruptedException e) { + } + if (hotUpdateActive) { + checkForUpdates(); + } + } + logger.info("Tuscany contribution hotupdate stopped"); + } + }; + hotUpdateThread = new Thread(runable, "TuscanyHotUpdate"); + hotUpdateActive = true; + hotUpdateThread.start(); + } + + + /** + * Checks if any of the contributions have been updated and if so restarts the sca domain + * TODO: Ideally just the altered contribution would be restarted but thats not possible + * as the classloader used by the SCADomain includes the old contribution so need + * to restart the entire domain to use a new ClassLoader. Should there be seperate + * ClassLoader per contribution? But then have all the issues with sharing classes + * across contributions. + */ + protected void checkForUpdates() { + URL[] currentContributions = getContributionJarURLs(contributionRepository); + + if (areContributionsAltered(currentContributions)) { + try { + scaDomain.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + initEmbeddedSCADomain(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + protected boolean areContributionsAltered(URL[] currentContrabutions) { + try { + + List addedContributions = getAddedContributions(currentContrabutions); + List removedContributions = getRemovedContributions(currentContrabutions); + List updatedContributions = getUpdatedContributions(currentContrabutions); + + return (addedContributions.size() > 0 || removedContributions.size() > 0 || updatedContributions.size() > 0); + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + protected List getUpdatedContributions(URL[] currentContrabutions) throws URISyntaxException { + List urls = new ArrayList(); + for (URL url : currentContrabutions) { + if (existingContributions.containsKey(url)) { + File curentFile = new File(url.toURI()); + if (curentFile.lastModified() != existingContributions.get(url)) { + urls.add(url); + logger.info("updated contribution: " + curentFile.getName()); + } + } + } + return urls; + } + + protected List getRemovedContributions(URL[] currentContrabutions) throws URISyntaxException { + List currentUrls = Arrays.asList(currentContrabutions); + List urls = new ArrayList(); + for (URL url : existingContributions.keySet()) { + if (!currentUrls.contains(url)) { + urls.add(url); + } + } + for (URL url : urls) { + logger.info("removed contributions: " + new File(url.toURI()).getName()); + } + return urls; + } + + protected List getAddedContributions(URL[] currentContrabutions) throws URISyntaxException { + List urls = new ArrayList(); + for (URL url : currentContrabutions) { + if (!existingContributions.containsKey(url)) { + urls.add(url); + logger.info("added contribution: " + new File(url.toURI()).getName()); + } + } + return urls; + } + + @Override + public > R cast(B target) throws IllegalArgumentException { + throw new UnsupportedOperationException("not implemented"); + } + + @Override + public B getService(Class businessInterface, String serviceName) { + return scaDomain.getService(businessInterface, serviceName); + } + + @Override + public ServiceReference getServiceReference(Class businessInterface, String referenceName) { + return scaDomain.getServiceReference(businessInterface, referenceName); + } + + @Override + public String getURI() { + return domainURI; + } + + @Override + public ComponentManager getComponentManager(){ + return scaDomain.getComponentManager(); + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java new file mode 100644 index 0000000000..ffee6122d9 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java @@ -0,0 +1,407 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.host.embedded.impl; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.builder.DomainBuilder; +import org.apache.tuscany.sca.binding.sca.impl.SCABindingFactoryImpl; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.DefaultContextFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.impl.ContributionFactoryImpl; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.MessageFactoryImpl; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.work.Jsr237WorkScheduler; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.impl.SCADefinitionsImpl; +import org.apache.tuscany.sca.definitions.util.SCADefinitionsUtil; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.provider.DefaultSCADefinitionsProviderExtensionPoint; +import org.apache.tuscany.sca.provider.SCADefinitionsProvider; +import org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; + +public class ReallySmallRuntime { + private final static Logger logger = Logger.getLogger(ReallySmallRuntime.class.getName()); + private List modules; + private ExtensionPointRegistry registry; + + private ClassLoader classLoader; + private AssemblyFactory assemblyFactory; + private ContributionService contributionService; + private CompositeActivator compositeActivator; + private CompositeBuilder compositeBuilder; + private DomainBuilder domainBuilder; + private WorkScheduler workScheduler; + private ScopeRegistry scopeRegistry; + private ProxyFactory proxyFactory; + private List scaDefnsSink = new ArrayList(); + + public ReallySmallRuntime(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public void start() throws ActivationException { + long start = System.currentTimeMillis(); + + // Create our extension point registry + registry = new DefaultExtensionPointRegistry(); + registry.addExtensionPoint(registry); + + //Get work scheduler + + /* + * host-embedded + workScheduler = registry.getExtensionPoint(WorkScheduler.class); */ + + workScheduler = new Jsr237WorkScheduler(); + + // Create an interface contract mapper + InterfaceContractMapper mapper = new InterfaceContractMapperImpl(); + + // Get factory extension point + /* + * host-embedded + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class);*/ + + ModelFactoryExtensionPoint factories = new DefaultModelFactoryExtensionPoint(); + registry.addExtensionPoint(factories); + + // Create context factory extension point + ContextFactoryExtensionPoint contextFactories = new DefaultContextFactoryExtensionPoint(); + registry.addExtensionPoint(contextFactories); + + // Create Message factory + MessageFactory messageFactory = new MessageFactoryImpl(); + factories.addFactory(messageFactory); + + // Create a proxy factory + proxyFactory = ReallySmallRuntimeBuilder.createProxyFactory(registry, mapper, messageFactory); + + // Create model factories + assemblyFactory = new RuntimeAssemblyFactory(); + factories.addFactory(assemblyFactory); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + factories.addFactory(policyFactory); + + // Load the runtime modules + modules = loadModules(registry); + + registry.getExtensionPoint(ModelFactoryExtensionPoint.class).addFactory(new DefaultJavaInterfaceFactory()); + + // Start the runtime modules + startModules(registry, modules); + + factories.addFactory(new SCABindingFactoryImpl()); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + + IntentAttachPointTypeFactory intentAttachPointTypeFactory = new DefaultIntentAttachPointTypeFactory(); + factories.addFactory(intentAttachPointTypeFactory); + + factories.addFactory(new ContributionFactoryImpl()); + ContributionFactory contributionFactory = factories.getFactory(ContributionFactory.class); + + // Create a contribution service + contributionService = ReallySmallRuntimeBuilder.createContributionService(classLoader, + registry, + contributionFactory, + assemblyFactory, + policyFactory, + mapper, + scaDefnsSink); + + // Create the ScopeRegistry + scopeRegistry = ReallySmallRuntimeBuilder.createScopeRegistry(registry); + + // Create a composite activator + compositeActivator = ReallySmallRuntimeBuilder.createCompositeActivator(registry, + assemblyFactory, + messageFactory, + scaBindingFactory, + mapper, + proxyFactory, + scopeRegistry, + workScheduler); + + // Load the definitions.xml + loadSCADefinitions(registry); + + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is started in " + (end - start) + " ms."); + } + } + + public void stop() throws ActivationException { + long start = System.currentTimeMillis(); + + // Stop the runtime modules + stopModules(registry, modules); + + // Stop and destroy the work manager + workScheduler.destroy(); + + // Cleanup + modules = null; + registry = null; + assemblyFactory = null; + contributionService = null; + compositeActivator = null; + workScheduler = null; + scopeRegistry = null; + + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is stopped in " + (end - start) + " ms."); + } + } + + public void buildComposite(Composite composite) throws CompositeBuilderException { + //Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + factories.addFactory(new SCABindingFactoryImpl()); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + factories.addFactory(new DefaultIntentAttachPointTypeFactory()); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = factories.getFactory(IntentAttachPointTypeFactory.class); + InterfaceContractMapper mapper = new InterfaceContractMapperImpl(); + + //Create a composite builder + compositeBuilder = ReallySmallRuntimeBuilder.createCompositeBuilder(assemblyFactory, + scaBindingFactory, + intentAttachPointTypeFactory, + mapper); + compositeBuilder.build(composite); + + } + + public ContributionService getContributionService() { + return contributionService; + } + + public CompositeActivator getCompositeActivator() { + return compositeActivator; + } + + public CompositeBuilder getCompositeBuilder() { + return compositeBuilder; + } + + public AssemblyFactory getAssemblyFactory() { + return assemblyFactory; + } + + public DomainBuilder getDomainBuilder() { + if ( domainBuilder == null ) { + //Create a domain builder + //Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = factories.getFactory(IntentAttachPointTypeFactory.class); + InterfaceContractMapper mapper = new InterfaceContractMapperImpl(); + domainBuilder = ReallySmallRuntimeBuilder.createDomainBuilder(assemblyFactory, + scaBindingFactory, + intentAttachPointTypeFactory, + mapper); + } + return domainBuilder; + } + + private void loadSCADefinitions(ExtensionPointRegistry registry) throws ActivationException { + try { + registry.addExtensionPoint(new DefaultSCADefinitionsProviderExtensionPoint(registry)); + + URLArtifactProcessorExtensionPoint documentProcessors = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + SCADefinitionsDocumentProcessor definitionsProcessor = (SCADefinitionsDocumentProcessor)documentProcessors.getProcessor(SCADefinitions.class); + SCADefinitionsProviderExtensionPoint scaDefnProviders = registry.getExtensionPoint(SCADefinitionsProviderExtensionPoint.class); + + SCADefinitions systemSCADefinitions = new SCADefinitionsImpl(); + SCADefinitions aSCADefn = null; + for ( SCADefinitionsProvider aProvider : scaDefnProviders.getSCADefinitionsProviders() ) { + aSCADefn = aProvider.getSCADefinition(); + SCADefinitionsUtil.aggregateSCADefinitions(aSCADefn, systemSCADefinitions); + } + + //we cannot expect that providers will add the intents and policysets into the resolver + //so we do this here explicitly + for ( Intent intent : systemSCADefinitions.getPolicyIntents() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(intent); + } + + for ( PolicySet policySet : systemSCADefinitions.getPolicySets() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(policySet); + } + + for ( IntentAttachPointType attachPoinType : systemSCADefinitions.getBindingTypes() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(attachPoinType); + } + + for ( IntentAttachPointType attachPoinType : systemSCADefinitions.getImplementationTypes() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(attachPoinType); + } + + //now that all system sca definitions have been read, lets resolve them rightaway + definitionsProcessor.resolve(systemSCADefinitions, + definitionsProcessor.getSCADefinitionsResolver()); + } catch ( Exception e ) { + throw new ActivationException(e); + } + + /*URLArtifactProcessorExtensionPoint documentProcessors = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + SCADefinitionsDocumentProcessor definitionsProcessor = (SCADefinitionsDocumentProcessor)documentProcessors.getProcessor(SCADefinitions.class); + + try { + Map> scaDefinitionFiles = + ServiceDiscovery.getInstance().getServiceResources("definitions.xml"); + + SCADefinitions systemSCADefinitions = new SCADefinitionsImpl(); + for ( ClassLoader cl : scaDefinitionFiles.keySet() ) { + for ( URL scaDefnUrl : scaDefinitionFiles.get(cl) ) { + SCADefinitions defnSubset = definitionsProcessor.read(null, null, scaDefnUrl); + SCADefinitionsUtil.aggregateSCADefinitions(defnSubset, systemSCADefinitions); + } + } + + definitionsProcessor.resolve(systemSCADefinitions, definitionsProcessor.getSCADefinitionsResolver()); + scaDefnsSink.add(systemSCADefinitions); + } catch ( ContributionReadException e ) { + throw new ActivationException(e); + } catch ( ContributionResolveException e ) { + throw new ActivationException(e); + } catch ( IOException e ) { + throw new ActivationException(e); + }*/ + } + + @SuppressWarnings("unchecked") + private List loadModules(ExtensionPointRegistry registry) throws ActivationException { + + // Load and instantiate the modules found on the classpath (or any registered classloaders) + modules = new ArrayList(); + try { + Set moduleActivators = + ServiceDiscovery.getInstance().getServiceDeclarations(ModuleActivator.class); + Set moduleClasses = new HashSet(); + for (ServiceDeclaration moduleDeclarator : moduleActivators) { + if (moduleClasses.contains(moduleDeclarator.getClassName())) { + continue; + } + moduleClasses.add(moduleDeclarator.getClassName()); + Class moduleClass = moduleDeclarator.loadClass(); + ModuleActivator module = (ModuleActivator)moduleClass.newInstance(); + modules.add(module); + } + } catch (IOException e) { + throw new ActivationException(e); + } catch (ClassNotFoundException e) { + throw new ActivationException(e); + } catch (InstantiationException e) { + throw new ActivationException(e); + } catch (IllegalAccessException e) { + throw new ActivationException(e); + } + + return modules; + } + + private void startModules(ExtensionPointRegistry registry, List modules) + throws ActivationException { + boolean debug = logger.isLoggable(Level.FINE); + // Start all the extension modules + for (ModuleActivator module : modules) { + long start = 0L; + if (debug) { + logger.fine(module.getClass().getName() + " is starting."); + start = System.currentTimeMillis(); + } + module.start(registry); + if (debug) { + long end = System.currentTimeMillis(); + logger.fine(module.getClass().getName() + " is started in " + (end - start) + " ms."); + } + } + } + + private void stopModules(ExtensionPointRegistry registry, List modules) { + boolean debug = logger.isLoggable(Level.FINE); + for (ModuleActivator module : modules) { + long start = 0L; + if (debug) { + logger.fine(module.getClass().getName() + " is stopping."); + start = System.currentTimeMillis(); + } + module.stop(registry); + if (debug) { + long end = System.currentTimeMillis(); + logger.fine(module.getClass().getName() + " is stopped in " + (end - start) + " ms."); + } + } + } + + /** + * @return the proxyFactory + */ + public ProxyFactory getProxyFactory() { + return proxyFactory; + } + + /** + * @return the registry + */ + public ExtensionPointRegistry getExtensionPointRegistry() { + return registry; + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java new file mode 100644 index 0000000000..4f155473d8 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java @@ -0,0 +1,297 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.io.IOException; +import java.util.List; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.DomainBuilder; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.assembly.builder.impl.DomainWireBuilderImpl; +import org.apache.tuscany.sca.assembly.xml.ComponentTypeDocumentProcessor; +import org.apache.tuscany.sca.assembly.xml.ComponentTypeProcessor; +import org.apache.tuscany.sca.assembly.xml.CompositeDocumentProcessor; +import org.apache.tuscany.sca.assembly.xml.CompositeProcessor; +import org.apache.tuscany.sca.assembly.xml.ConstrainingTypeDocumentProcessor; +import org.apache.tuscany.sca.assembly.xml.ConstrainingTypeProcessor; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultPackageProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultURLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultValidatingXMLInputFactory; +import org.apache.tuscany.sca.contribution.processor.DefaultValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensiblePackageProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.DefaultModelResolverExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionRepository; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.DefaultContributionListenerExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ExtensibleContributionListener; +import org.apache.tuscany.sca.contribution.service.TypeDescriber; +import org.apache.tuscany.sca.contribution.service.impl.ContributionRepositoryImpl; +import org.apache.tuscany.sca.contribution.service.impl.ContributionServiceImpl; +import org.apache.tuscany.sca.contribution.service.impl.PackageTypeDescriberImpl; +import org.apache.tuscany.sca.contribution.xml.ContributionMetadataProcessor; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.CompositeActivatorImpl; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.conversation.ConversationManagerImpl; +import org.apache.tuscany.sca.core.invocation.DefaultProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.CompositeScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ConversationalScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.RequestScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopeRegistryImpl; +import org.apache.tuscany.sca.core.scope.StatelessScopeContainerFactory; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.provider.DefaultProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.DefaultWireProcessorExtensionPoint; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; + +import android.content.Context; + +public class ReallySmallRuntimeBuilder { + + public static ProxyFactory createProxyFactory(ExtensionPointRegistry registry, + InterfaceContractMapper mapper, + MessageFactory messageFactory) { + + ProxyFactory proxyFactory = new DefaultProxyFactoryExtensionPoint(messageFactory, mapper); + + // FIXME Pass these around differently as they are not extension points + registry.addExtensionPoint(proxyFactory); + registry.addExtensionPoint(mapper); + + return proxyFactory; + } + + public static CompositeActivator createCompositeActivator(ExtensionPointRegistry registry, + AssemblyFactory assemblyFactory, + MessageFactory messageFactory, + SCABindingFactory scaBindingFactory, + InterfaceContractMapper mapper, + ProxyFactory proxyFactory, + ScopeRegistry scopeRegistry, + WorkScheduler workScheduler) { + + // Create a wire post processor extension point + RuntimeWireProcessorExtensionPoint wireProcessors = new DefaultWireProcessorExtensionPoint(); + registry.addExtensionPoint(wireProcessors); + //registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class); + RuntimeWireProcessor wireProcessor = new ExtensibleWireProcessor(wireProcessors); + + // Retireve the processors extension point + registry.addExtensionPoint(new DefaultStAXArtifactProcessorExtensionPoint(registry.getExtensionPoint(ModelFactoryExtensionPoint.class))); + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + // Create a provider factory extension point + ProviderFactoryExtensionPoint providerFactories = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + registry.getExtensionPoint(ModelFactoryExtensionPoint.class).addFactory(new DefaultJavaInterfaceFactory()); + + JavaInterfaceFactory javaInterfaceFactory = + registry.getExtensionPoint(ModelFactoryExtensionPoint.class).getFactory(JavaInterfaceFactory.class); + RequestContextFactory requestContextFactory = + registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class); + + ConversationManager conversationManager = new ConversationManagerImpl(); + registry.addExtensionPoint(conversationManager); + + // Create the composite activator + CompositeActivator compositeActivator = + new CompositeActivatorImpl(assemblyFactory, messageFactory, javaInterfaceFactory, scaBindingFactory, + mapper, scopeRegistry, workScheduler, wireProcessor, requestContextFactory, + proxyFactory, providerFactories, processors, conversationManager); + + return compositeActivator; + } + + public static CompositeBuilder createCompositeBuilder(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper) { + return new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, null); + } + + public static DomainBuilder createDomainBuilder(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper) { + return new DomainWireBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, null); + } + + /** + * Create the contribution service used by this domain. + * + * @throws ActivationException + */ + public static ContributionService createContributionService(ClassLoader classLoader, + ExtensionPointRegistry registry, + ContributionFactory contributionFactory, + AssemblyFactory assemblyFactory, + PolicyFactory policyFactory, + InterfaceContractMapper mapper, + List scaDefinitionsSink) + throws ActivationException { + + // Create a validation XML schema extension point + + /* host-embedded + * ValidationSchemaExtensionPoint schemas = registry.getExtensionPoint(ValidationSchemaExtensionPoint.class); + */ + + ValidationSchemaExtensionPoint schemas = new DefaultValidationSchemaExtensionPoint(); + registry.addExtensionPoint(schemas); + + //schemas.addSchema(ReallySmallRuntimeBuilder.class.getClassLoader().getResource("tuscany-sca.xsd").toString()); + + // Create a new XML input factory + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + + // Create a validating XML input factory + XMLInputFactory validatingInputFactory = new DefaultValidatingXMLInputFactory(inputFactory, schemas); + + // Create STAX artifact processor extension point + //StAXArtifactProcessorExtensionPoint staxProcessors = + // ; + + StAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(registry.getExtensionPoint(ModelFactoryExtensionPoint.class)); + registry.addExtensionPoint(staxProcessors); + + // Create and register STAX processors for SCA assembly XML + ExtensibleStAXArtifactProcessor staxProcessor = + new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(contributionFactory, assemblyFactory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(assemblyFactory, policyFactory, staxProcessor)); + staxProcessors + .addArtifactProcessor(new ConstrainingTypeProcessor(assemblyFactory, policyFactory, staxProcessor)); + + // Register STAX processors for Contribution Metadata + staxProcessors.addArtifactProcessor(new ContributionMetadataProcessor(assemblyFactory, contributionFactory, + staxProcessor)); + + // Create URL artifact processor extension point + URLArtifactProcessorExtensionPoint documentProcessors = new DefaultURLArtifactProcessorExtensionPoint(registry.getExtensionPoint(ModelFactoryExtensionPoint.class)); + registry.addExtensionPoint(documentProcessors); + //registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + + // Create and register document processors for SCA assembly XML + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, validatingInputFactory, scaDefinitionsSink)); + documentProcessors.addArtifactProcessor(new ComponentTypeDocumentProcessor(staxProcessor, validatingInputFactory)); + documentProcessors.addArtifactProcessor(new ConstrainingTypeDocumentProcessor(staxProcessor, validatingInputFactory)); + + // Create and register document processor for definitions.xml + //TODO No XMLSchema validation for definitions.xml for now + // as the XSD for it is not quite right yet + SCADefinitionsDocumentProcessor definitionsDocumentProcessor = + new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, inputFactory, policyFactory); + documentProcessors.addArtifactProcessor(definitionsDocumentProcessor); + ModelResolver domainModelResolver = definitionsDocumentProcessor.getSCADefinitionsResolver(); + + // Create Model Resolver extension point + ModelResolverExtensionPoint modelResolvers = new DefaultModelResolverExtensionPoint(); + registry.addExtensionPoint(modelResolvers); + + // Create contribution package processor extension point + TypeDescriber describer = new PackageTypeDescriberImpl(); + PackageProcessor packageProcessor = + new ExtensiblePackageProcessor(new DefaultPackageProcessorExtensionPoint(), describer); + + // Get the model factory extension point + ModelFactoryExtensionPoint modelFactories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + + registry.addExtensionPoint(new DefaultContributionListenerExtensionPoint(modelFactories)); + + // Create contribution listener + ExtensibleContributionListener contributionListener = + new ExtensibleContributionListener(registry.getExtensionPoint(ContributionListenerExtensionPoint.class)); + + // Create a contribution repository + ContributionRepository repository = null; + try { + repository = new ContributionRepositoryImpl("target", inputFactory); + } catch (IOException e) { + //throw new ActivationException(e); + } + + ExtensibleURLArtifactProcessor documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors); + + // Create the contribution service + ContributionService contributionService = + new ContributionServiceImpl(repository, packageProcessor, documentProcessor, staxProcessor, + contributionListener, domainModelResolver, modelResolvers, modelFactories, + assemblyFactory, contributionFactory, inputFactory, scaDefinitionsSink); + return contributionService; + } + + public static ScopeRegistry createScopeRegistry(ExtensionPointRegistry registry) { + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(); + ScopeContainerFactory[] factories = + new ScopeContainerFactory[] {new CompositeScopeContainerFactory(), new StatelessScopeContainerFactory(), + new RequestScopeContainerFactory(), + new ConversationalScopeContainerFactory(null), + // new HttpSessionScopeContainer(monitor) + }; + for (ScopeContainerFactory f : factories) { + scopeRegistry.register(f); + } + + //FIXME Pass the scope container differently as it's not an extension point + registry.addExtensionPoint(scopeRegistry); + + return scopeRegistry; + } + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java new file mode 100644 index 0000000000..01adc4df82 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.management; + +import java.util.EventListener; + +public interface ComponentListener extends EventListener { + + void componentStarted(String componentName); + void componentStopped(String componentName); + +} diff --git a/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java new file mode 100644 index 0000000000..b5e41dd097 --- /dev/null +++ b/branches/sca-android/host-android/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.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.host.embedded.management; + +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.core.assembly.ActivationException; + +public interface ComponentManager { + + Set getComponentNames(); + + Component getComponent(String componentName); + + boolean isComponentStarted(String componentName); + + void startComponent(String componentName) throws ActivationException; + + void stopComponent(String componentName) throws ActivationException; + + void addComponentListener(ComponentListener listener); + + void removeComponentListener(ComponentListener listener); + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java new file mode 100644 index 0000000000..10491df403 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.osoa.sca.ServiceReference; + + + +/** + * Test creation of an SCADomainBean and invocation of a service. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class SCADomainBeanTestCase extends TestCase { + + private SCADomainBean domain; + + @Override + protected void setUp() throws Exception { + domain = new SCADomainBean(); + domain.setDeployableComposites("test.composite"); + } + + public void testInvoke() throws Exception { + ServiceReference serviceReference = domain.getServiceReference(TestService.class, "TestServiceComponent"); + assertNotNull(serviceReference); + TestService service = serviceReference.getService(); + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java new file mode 100644 index 0000000000..67743517c2 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.osoa.sca.ServiceReference; + + + +/** + * Test SCADomain.newInstance and invocation of a service. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class SCADomainTestCase extends TestCase { + + private SCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = SCADomain.newInstance(null, "test.composite"); + } + + public void testInvoke() throws Exception { + ServiceReference serviceReference = domain.getServiceReference(TestService.class, "TestServiceComponent"); + assertNotNull(serviceReference); + TestService service = serviceReference.getService(); + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java new file mode 100644 index 0000000000..7f29553994 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.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.host.embedded.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; + + +/** + * Test creation of DefaultSCADomain. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class DefaultSCADomainTestCase extends TestCase { + private DefaultSCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = new DefaultSCADomain(getClass().getClassLoader(), null, + "http://localhost", ".", "test.composite"); + } + + public void testStart() throws Exception { + TestService service = domain.getService(TestService.class, "TestServiceComponent"); + assertNotNull(service); + } + + public void testComponentManager() throws Exception { + ComponentManager componentManager = domain.getComponentManager(); + assertEquals(1, componentManager.getComponentNames().size()); + assertEquals("TestServiceComponent", componentManager.getComponentNames().iterator().next()); + assertNotNull(componentManager.getComponent("TestServiceComponent")); + + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + componentManager.stopComponent("TestServiceComponent"); + assertFalse(componentManager.isComponentStarted("TestServiceComponent")); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java new file mode 100644 index 0000000000..6e71295044 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.net.URL; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; + +/** + * Test creation of an EmbeddedSCADomain and invocation of a service. + * + * @version $Rev: 637129 $ $Date: 2008-03-14 08:11:59 -0700 (Fri, 14 Mar 2008) $ + */ +public class EmbeddedSCADomainTestCase extends TestCase { + private EmbeddedSCADomain domain; + + @Override + protected void setUp() throws Exception { + + // Create a test embedded SCA domain + domain = new EmbeddedSCADomain(getClass().getClassLoader(), "http://localhost"); + } + + public void testDomain() throws Exception { + // Start the domain + domain.start(); + + // Determine my class loader and my test SCA contribution location + ClassLoader myClassLoader = getClass().getClassLoader(); + String url = myClassLoader.getResource("test.txt").toString(); + url = url.substring(0, url.length()-8); + + // Contribute the SCA contribution + TestModelResolver myResolver = new TestModelResolver(myClassLoader); + ContributionService contributionService = domain.getContributionService(); + Contribution contribution = contributionService.contribute("http://test/contribution", new URL(url), myResolver, false); + assertNotNull(contribution); + + // Decide which SCA composite I want to deploy + Composite myComposite = myResolver.getComposite(new QName("http://test", "test")); + + // Add the deployable composite to the domain + domain.getDomainComposite().getIncludes().add(myComposite); + + + domain.buildComposite(myComposite); + + // Start the composite + domain.getCompositeActivator().activate(myComposite); + domain.getCompositeActivator().start(myComposite); + + // At this point the domain contains my contribution, my composite and + // it's started, my application code can start using it + + // Get the TestServiceComponent service + TestService service = domain.getService(TestService.class, "TestServiceComponent"); + + // Invoke the service + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + + // Stop my composite + domain.getCompositeActivator().stop(myComposite); + domain.getCompositeActivator().deactivate(myComposite); + + // Remove my composite + domain.getDomainComposite().getIncludes().remove(myComposite); + + // Remove my contribution + contributionService.remove("http://test/contribution"); + + // Stop the domain + domain.stop(); + } + + public void testComponentManager() throws Exception { + // Start the domain + domain.start(); + + // Determine my class loader and my test SCA contribution location + ClassLoader myClassLoader = getClass().getClassLoader(); + String url = myClassLoader.getResource("test.txt").toString(); + url = url.substring(0, url.length()-8); + + // Contribute the SCA contribution + TestModelResolver myResolver = new TestModelResolver(myClassLoader); + ContributionService contributionService = domain.getContributionService(); + Contribution contribution = contributionService.contribute("http://test/contribution", new URL(url), myResolver, false); + assertNotNull(contribution); + + // Decide which SCA composite I want to deploy + Composite myComposite = myResolver.getComposite(new QName("http://test", "test")); + + // Add the deployable composite to the domain + domain.getDomainComposite().getIncludes().add(myComposite); + + domain.buildComposite(myComposite); + + // Start the composite + domain.getCompositeActivator().activate(myComposite); + domain.getCompositeActivator().start(myComposite); + + // At this point the domain contains my contribution, my composite and + // it's started, my application code can start using it + + ComponentManager componentManager = domain.getComponentManager(); + assertEquals(1, componentManager.getComponentNames().size()); + assertEquals("TestServiceComponent", componentManager.getComponentNames().iterator().next()); + + Component component = componentManager.getComponent("TestServiceComponent"); + assertNotNull(component); + assertEquals("TestServiceComponent", component.getName()); + + MyComponentListener cl = new MyComponentListener(); + componentManager.addComponentListener(cl); + + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + + assertFalse(cl.stopCalled); + componentManager.stopComponent("TestServiceComponent"); + assertTrue(cl.stopCalled); + assertFalse(componentManager.isComponentStarted("TestServiceComponent")); + + assertFalse(cl.startCalled); + componentManager.startComponent("TestServiceComponent"); + assertTrue(cl.startCalled); + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + + // Stop my composite + domain.getCompositeActivator().stop(myComposite); + domain.getCompositeActivator().deactivate(myComposite); + + // Remove my composite + domain.getDomainComposite().getIncludes().remove(myComposite); + + // Remove my contribution + contributionService.remove("http://test/contribution"); + + // Stop the domain + domain.stop(); + } + + class MyComponentListener implements ComponentListener { + boolean startCalled; + boolean stopCalled; + + public void componentStarted(String componentName) { + startCalled = true; + } + + public void componentStopped(String componentName) { + stopCalled = true; + } + + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java new file mode 100644 index 0000000000..10c174a00b --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.host.embedded.impl; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A test model resolver, based on a map. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map map = new HashMap(); + private WeakReference classLoader; + + private Map composites = new HashMap(); + + public TestModelResolver(ClassLoader classLoader) { + this.classLoader = new WeakReference(classLoader); + } + + public T resolveModel(Class modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else if (unresolved instanceof ClassReference) { + + // Load a class on demand + ClassReference classReference = (ClassReference)unresolved; + Class clazz; + try { + clazz = Class.forName(classReference.getClassName(), true, classLoader.get()); + } catch (ClassNotFoundException e) { + + // Return the unresolved object + return unresolved; + } + + // Store a new ClassReference wrappering the loaded class + resolved = new ClassReference(clazz); + map.put(resolved, resolved); + + // Return the resolved ClassReference + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + if (resolved instanceof Composite) { + Composite composite = (Composite)resolved; + composites.put(composite.getName(), composite); + } + } + + public Object removeModel(Object resolved) { + if (resolved instanceof Composite) { + Composite composite = (Composite)resolved; + composites.remove(composite.getName()); + } + return map.remove(resolved); + } + + public Composite getComposite(QName qname) { + return composites.get(qname); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java new file mode 100644 index 0000000000..3a215e537d --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.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.host.embedded.test.extension; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.impl.TestImplementationImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * Default factory for the test implementation model. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class DefaultTestImplementationFactory implements TestImplementationFactory { + + private AssemblyFactory assemblyFactory; + private JavaInterfaceFactory javaFactory; + + public DefaultTestImplementationFactory(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory) { + this.assemblyFactory = assemblyFactory; + this.javaFactory = javaFactory; + } + + public TestImplementation createTestImplementation() { + return new TestImplementationImpl(assemblyFactory, javaFactory); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java new file mode 100644 index 0000000000..5aea0a1dd1 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.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.host.embedded.test.extension; + +import org.apache.tuscany.sca.assembly.Implementation; + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $$Rev: 608205 $$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public interface TestImplementation extends Implementation { + + /** + * Returns the greeting string that can be configured on test implementations. + * + * @return the greeting string that can be configured on test implementations + */ + public String getGreeting(); + + /** + * Sets the greeting string that can be configured on test implementations. + * + * @param greeting the greeting string that can be configured on test implementations + */ + public void setGreeting(String greeting); + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java new file mode 100644 index 0000000000..4173d1b4e0 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.test.extension; + + +/** + * A factory for the test implementation model. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public interface TestImplementationFactory { + + /** + * Creates a new test implementation. + * + * @return + */ + TestImplementation createTestImplementation(); + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java new file mode 100644 index 0000000000..3ed64536ef --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension; + +/** + * Service interface for test component implementations. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public interface TestService { + + String ping(String name); + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java new file mode 100644 index 0000000000..c0dd04ce33 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.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.host.embedded.test.extension.impl; + +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $$Rev: 608205 $$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public class TestImplementationImpl implements TestImplementation { + + private Service testService; + private String greeting; + + /** + * Constructs a new test implementation. + */ + public TestImplementationImpl(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory) { + + // Test implementations always provide a single service exposing + // the TestService interface, and have no references and properties + testService = assemblyFactory.createService(); + testService.setName("Test"); + JavaInterface javaInterface; + try { + javaInterface = javaFactory.createJavaInterface(TestService.class); + } catch (InvalidInterfaceException e) { + throw new IllegalArgumentException(e); + } + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterface); + testService.setInterfaceContract(interfaceContract); + } + + public String getGreeting() { + return greeting; + } + + public void setGreeting(String greeting) { + this.greeting = greeting; + } + + public ConstrainingType getConstrainingType() { + // The test implementation does not support constrainingTypes + return null; + } + + public List getProperties() { + // The test implementation does not support properties + return Collections.emptyList(); + } + + public List getServices() { + // The test implementation provides a single fixed Test service + return Collections.singletonList(testService); + } + + public List getReferences() { + // The test implementation does not support properties + return Collections.emptyList(); + } + + public String getURI() { + // The test implementation does not have a URI + return null; + } + + public void setConstrainingType(ConstrainingType constrainingType) { + // The test implementation does not support constrainingTypes + } + + public void setURI(String uri) { + // The test implementation does not have a URI + } + + public boolean isUnresolved() { + // The test implementation is always resolved + return false; + } + + public void setUnresolved(boolean unresolved) { + // The test implementation is always resolved + } +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java new file mode 100644 index 0000000000..63412012ef --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension.impl; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +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.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementationFactory; + + + +/** + * Implements a STAX artifact processor for test implementations. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class TestImplementationProcessor implements StAXArtifactProcessor { + private static final QName IMPLEMENTATION_TEST = new QName("http://test/extension", "implementation.test"); + + private TestImplementationFactory testFactory; + + public TestImplementationProcessor(TestImplementationFactory testFactory) { + this.testFactory = testFactory; + } + + public QName getArtifactType() { + // Returns the qname of the XML element processed by this processor + return IMPLEMENTATION_TEST; + } + + public Class getModelType() { + // Returns the type of model processed by this processor + return TestImplementation.class; + } + + public TestImplementation read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + + // Read an element + + // Read the message attribute. + String message = reader.getAttributeValue(null, "greeting"); + + // Create and initialize the test implementation model + TestImplementation implementation = testFactory.createTestImplementation(); + implementation.setGreeting(message); + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && IMPLEMENTATION_TEST.equals(reader.getName())) { + break; + } + } + + return implementation; + } + + public void resolve(TestImplementation impl, ModelResolver resolver) throws ContributionResolveException { + } + + public void write(TestImplementation implementation, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + writer.writeStartElement(IMPLEMENTATION_TEST.getNamespaceURI(), IMPLEMENTATION_TEST.getLocalPart()); + + if (implementation.getGreeting() != null) { + writer.writeAttribute("greeting", implementation.getGreeting()); + } + + writer.writeEndElement(); + } +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java new file mode 100644 index 0000000000..ac8339b6ed --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.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.host.embedded.test.extension.module; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementationFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.DefaultTestImplementationFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.impl.TestImplementationProcessor; +import org.apache.tuscany.sca.host.embedded.test.extension.provider.TestImplementationProviderFactory; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; + + + +/** + * Implements a module activator for the test implementation extension module. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class TestModuleActivator implements ModuleActivator { + + public void start(ExtensionPointRegistry registry) { + + // Create the test implementation factory + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = factories.getFactory(AssemblyFactory.class); + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + TestImplementationFactory testFactory = new DefaultTestImplementationFactory(assemblyFactory, javaFactory); + factories.addFactory(testFactory); + + // Add the test implementation extension to the StAXArtifactProcessor + // extension point + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + TestImplementationProcessor implementationArtifactProcessor = new TestImplementationProcessor(testFactory); + processors.addArtifactProcessor(implementationArtifactProcessor); + + // Add the test provider factory to the ProviderFactory extension point + ProviderFactoryExtensionPoint providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + providerFactories.addProviderFactory(new TestImplementationProviderFactory()); + } + + public void stop(ExtensionPointRegistry registry) { + } +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java new file mode 100644 index 0000000000..3ab1041ada --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.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.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + + +/** + * Implementation provider for test implementations. + * + * @version $$Rev: 608205 $$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public class TestImplementationProvider implements ImplementationProvider { + + private RuntimeComponent component; + private TestImplementation implementation; + + /** + * Constructs a new test implementation provider. + */ + public TestImplementationProvider(RuntimeComponent component, TestImplementation implementation) { + this.component = component; + this.implementation = implementation; + } + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + TestInvoker invoker = new TestInvoker(operation, implementation.getGreeting()); + return invoker; + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public void start() { + System.out.println("Starting " + component.getName()); + } + + public void stop() { + System.out.println("Stopping " + component.getName()); + } + +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java new file mode 100644 index 0000000000..ac3724f429 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.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.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $$Rev: 608205 $$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public class TestImplementationProviderFactory implements ImplementationProviderFactory { + + /** + * Constructs a new test implementation provider factory. + */ + public TestImplementationProviderFactory() { + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, TestImplementation implementation) { + return new TestImplementationProvider(component, implementation); + } + + public Class getModelType() { + return TestImplementation.class; + } +} diff --git a/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java new file mode 100644 index 0000000000..b13a218064 --- /dev/null +++ b/branches/sca-android/host-android/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + + +/** + * Implements an invoker for test component implementations. + * + * The target invoker is responsible for handling operation invocations. + * + * @version $Rev: 608205 $ $Date: 2008-01-02 12:29:05 -0800 (Wed, 02 Jan 2008) $ + */ +public class TestInvoker implements Invoker { + private Operation operation; + private String greeting; + + public TestInvoker(Operation operation, String greeting) { + this.operation = operation; + this.greeting = greeting; + } + + public Message invoke(Message msg) { + Object[] args = msg.getBody(); + if (operation.getName().equals("ping")) { + msg.setBody(greeting + " " + args[0]); + } else { + msg.setFaultBody(new Exception("Operation " + operation.getName() + " is not supported")); + } + return msg; + } +} diff --git a/branches/sca-android/host-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator b/branches/sca-android/host-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator new file mode 100644 index 0000000000..7e2e11e4cc --- /dev/null +++ b/branches/sca-android/host-android/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator @@ -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. +# Implementation class for the ExtensionActivator +org.apache.tuscany.sca.host.embedded.test.extension.module.TestModuleActivator diff --git a/branches/sca-android/host-android/src/test/resources/test.composite b/branches/sca-android/host-android/src/test/resources/test.composite new file mode 100644 index 0000000000..fcd33d3fcb --- /dev/null +++ b/branches/sca-android/host-android/src/test/resources/test.composite @@ -0,0 +1,30 @@ + + + + + + + + + diff --git a/branches/sca-android/host-android/src/test/resources/test.txt b/branches/sca-android/host-android/src/test/resources/test.txt new file mode 100644 index 0000000000..7b13a7e01f --- /dev/null +++ b/branches/sca-android/host-android/src/test/resources/test.txt @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. \ No newline at end of file diff --git a/branches/sca-android/interface-java-jaxws/.classpath b/branches/sca-android/interface-java-jaxws/.classpath new file mode 100644 index 0000000000..c86b7b792b --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/.classpath @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/interface-java-jaxws/.project b/branches/sca-android/interface-java-jaxws/.project new file mode 100644 index 0000000000..6390d9d016 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/.project @@ -0,0 +1,30 @@ + + tuscany-interface-java-jaxws + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-assembly-xml + tuscany-contribution + tuscany-contribution-java + tuscany-contribution-namespace + tuscany-core + tuscany-core-spi + tuscany-databinding + tuscany-databinding-jaxb + tuscany-definitions + tuscany-extensibility + tuscany-interface + tuscany-interface-java + tuscany-interface-java-xml + tuscany-policy + tuscany-sca-api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/interface-java-jaxws/DISCLAIMER b/branches/sca-android/interface-java-jaxws/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/interface-java-jaxws/LICENSE b/branches/sca-android/interface-java-jaxws/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/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/branches/sca-android/interface-java-jaxws/NOTICE b/branches/sca-android/interface-java-jaxws/NOTICE new file mode 100644 index 0000000000..94481d6cfa --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/interface-java-jaxws/pom.xml b/branches/sca-android/interface-java-jaxws/pom.xml new file mode 100644 index 0000000000..e8d83e816e --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/pom.xml @@ -0,0 +1,188 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-interface-java-jaxws + Apache Tuscany Java Interface for JAXWS + + + + org.apache.tuscany.sca + tuscany-core-spi + 2.0-incubating-SNAPSHOT + + + org.apache.tuscany.sca + tuscany-databinding-jaxb + 2.0-incubating-SNAPSHOT + + + org.apache.tuscany.sca + tuscany-interface-java-xml + 2.0-incubating-SNAPSHOT + + + + junit + junit + 4.2 + test + + + + javax.xml.ws + jaxws-api + 2.1 + + + + + + + java.net + java.net Maven 1.x Repository + http://download.java.net/maven/1 + legacy + + + + + + java.net2 + java.net Maven 2.x Repository + http://download.java.net/maven/2 + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Djava.endorsed.dirs=target/endorsed + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + generate-sources + + copy + + + + + javax.xml.ws + jaxws-api + 2.1 + jar + + + javax.xml.bind + jaxb-api + 2.1 + jar + + + ${project.build.directory}/endorsed + false + true + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.0 + + + add-test-source + generate-sources + + add-test-source + + + + target/jaxws-source + + + + + + + org.codehaus.mojo + jaxws-maven-plugin + 1.9 + + + process-resources + + wsimport + + + + + com.example.stock + ${basedir}/src/test/resources/wsdl + + + StockExceptionTest.wsdl + + ${project.build.directory}/jaxws-source + false + true + + + + + + + diff --git a/branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java b/branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java new file mode 100644 index 0000000000..dbbc7b4635 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import javax.xml.namespace.QName; +import javax.xml.ws.WebFault; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.util.FaultException; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.osoa.sca.ServiceRuntimeException; + +/** + * JAX-WS ExceptionHandler + * + * @version $Rev: 639821 $ $Date: 2008-03-21 12:42:37 -0800 (Fri, 21 Mar 2008) $ + */ +public class JAXWSFaultExceptionMapper implements FaultExceptionMapper { + private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; + private DataBindingExtensionPoint dataBindingExtensionPoint; + + public JAXWSFaultExceptionMapper(DataBindingExtensionPoint dataBindingExtensionPoint) { + super(); + this.dataBindingExtensionPoint = dataBindingExtensionPoint; + } + + /** + * The following is quoted from the JAX-WS Specification v2.1 + *
    + *
  • WrapperException(String message, FaultBean faultInfo)
    + * A constructor where WrapperException is replaced with the name of the + * generated wrapper exception and FaultBean is replaced by the name of the + * generated fault bean. + *
  • WrapperException(String message, FaultBean faultInfo, Throwable + * cause)
    + * A constructor where WrapperException is replaced with the name of the + * generated wrapper exception and FaultBean is replaced by the name of the + * generated fault bean. The last argument, cause, may be used to convey + * protocol specific fault information + *
+ */ + @SuppressWarnings("unchecked") + public Throwable wrapFaultInfo(DataType exceptionType, String message, Object faultInfo, Throwable cause) { + Class exceptionClass = exceptionType.getPhysical(); + if (exceptionClass.isInstance(faultInfo)) { + return (Throwable)faultInfo; + } + DataType faultBeanType = exceptionType.getLogical(); + Class faultBeanClass = faultBeanType.getPhysical(); + try { + Exception exc = null; + try { + Constructor constructor = + exceptionClass.getConstructor(new Class[] {String.class, faultBeanClass, Throwable.class}); + exc = (Exception)constructor.newInstance(new Object[] {message, faultInfo, cause}); + } catch (NoSuchMethodException e) { + // Create a generic fault exception + exc = new FaultException(message, faultInfo, cause); + } + // Include the elem name into the FaultException we build so it can be used for matching in the DataTransformationInterceptor + // + // Note this may happen even if we find a constructor above, that is the type of the non-generic fault exc may be an instance + // of FaultException + // + if ((exc instanceof FaultException) && (faultBeanType.getLogical() instanceof XMLType)) { + FaultException faultExc = (FaultException)exc; + DataType faultBeanXMLType = (DataType)faultBeanType; + XMLType faultLogical = faultBeanXMLType.getLogical(); + faultExc.setFaultName(faultLogical.getElementName()); + } + return exc; + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + public Object getFaultInfo(Throwable exception, Class faultBeanClass) { + if (exception == null) { + return null; + } + + // Check if it's the generic FaultException + if (exception instanceof FaultException) { + return ((FaultException)exception).getFaultInfo(); + } + + try { + Method method = exception.getClass().getMethod("getFaultInfo", EMPTY_CLASS_ARRAY); + return method.invoke(exception, (Object[])null); + } catch (NoSuchMethodException e) { + // Follow the JAX-WS v2.1 Specification section 3.7 + return createFaultBean(exception, faultBeanClass); + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + private Object createFaultBean(Throwable exception, Class faultBeanClass) { + /** + * For each getter in the exception and its superclasses, a property of the same + * type and name is added to the bean. The getCause, getLocalizedMessage and + * getStackTrace getters from java.lang.Throwable and the getClass getter from + * java.lang.Object are excluded from the list of getters to be mapped. + */ + // Return the exception as-is if it's already the fault bean + if (faultBeanClass.isInstance(exception)) { + return exception; + } + try { + Object faultBean = null; + for (Constructor ctor : faultBeanClass.getConstructors()) { + Class[] params = ctor.getParameterTypes(); + if (params.length == 1 && String.class == params[0]) { + faultBean = ctor.newInstance(exception.getMessage()); + } else if (params.length == 2 && String.class == params[0] + && Throwable.class.isAssignableFrom(params[1])) { + faultBean = ctor.newInstance(exception.getMessage(), exception); + } else if (params.length == 0) { + faultBean = ctor.newInstance(); + } + if (faultBean != null) { + break; + } + } + if (faultBean == null) { + return exception; + } + BeanInfo beanInfo = Introspector.getBeanInfo(exception.getClass()); + for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { + Method getter = pd.getReadMethod(); + String name = getter.getName(); + if ("getClass".equals(name) || "getStackTrace".equals(name) + || "getCause".equals(name) + || "getLocalizedMessage".equals(name)) { + continue; + } + String prefix = "get"; + if (name.startsWith("get")) { + prefix = "get"; + } else if (name.startsWith("is")) { + prefix = "is"; + } + Method setter = null; + try { + setter = + faultBeanClass.getMethod("set" + name.substring(prefix.length()), new Class[] {getter + .getReturnType()}); + } catch (NoSuchMethodException e) { + continue; + } + Object prop = setter.invoke(faultBean, getter.invoke(exception, (Object[])null)); + setter.invoke(faultBean, prop); + } + return faultBean; + } catch (Throwable ex) { + throw new IllegalArgumentException(ex); + } + } + + @SuppressWarnings("unchecked") + public boolean introspectFaultDataType(DataType exceptionType) { + QName faultName = null; + boolean result = false; + + Class cls = exceptionType.getPhysical(); + if (cls == FaultException.class) { + return true; + } + DataType faultType = (DataType)exceptionType.getLogical(); + Class faultBean = null; + WebFault fault = cls.getAnnotation(WebFault.class); + if (fault != null) { + faultName = new QName(fault.targetNamespace(), fault.name()); + XMLType xmlType = new XMLType(faultName, null); + faultType.setLogical(xmlType); + if (!"".equals(fault.faultBean())) { + try { + faultBean = Class.forName(fault.faultBean(), false, cls.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new ServiceRuntimeException(e); + } + } else { + Method m; + try { + m = cls.getMethod("getFaultInfo", (Class[])null); + faultBean = m.getReturnType(); + } catch (NoSuchMethodException e) { + // Ignore + } + } + } + + if (faultBean == null) { + String faultBeanClassName = cls.getPackage().getName() + ".jaxws." + cls.getSimpleName() + "Bean"; + try { + faultBean = Class.forName(faultBeanClassName, false, cls.getClassLoader()); + } catch (ClassNotFoundException e) { + faultBean = cls; + } + } + + faultType.setPhysical(faultBean); + // TODO: Use the databinding framework to introspect the fault bean class + if (dataBindingExtensionPoint != null) { + result = + dataBindingExtensionPoint.introspectType(faultType, null, Throwable.class.isAssignableFrom(faultBean)); + } + + /* + The introspection of the fault DT may not have calculated the correct element name, + though we may have already done this in this method. Let's look at the DataType now + that introspection is done, and, if it has an XMLType, let's set the element to the + 'faultName' if we calculated one. + */ + if ((faultName != null) && (faultType.getLogical() instanceof XMLType)) { + XMLType faultTypeXML = (XMLType)faultType.getLogical(); + // The element name (if set) should match the fault name + faultTypeXML.setElementName(faultName); + } + + return result; + } + + public void setDataBindingExtensionPoint(DataBindingExtensionPoint dataBindingExtensionPoint) { + this.dataBindingExtensionPoint = dataBindingExtensionPoint; + } + +} diff --git a/branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java b/branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java new file mode 100644 index 0000000000..f25425f286 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/*import javax.jws.Oneway; +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.jws.soap.SOAPBinding.Style;*/ +import javax.xml.namespace.QName; +import javax.xml.ws.RequestWrapper; +import javax.xml.ws.ResponseWrapper; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Introspect the java class/interface with JSR-181 and JAXWS annotations + * + * @version $Rev: 643696 $ $Date: 2008-04-01 19:24:11 -0800 (Tue, 01 Apr 2008) $ + */ +public class JAXWSJavaInterfaceProcessor implements JavaInterfaceVisitor { + private static final String JAXB_DATABINDING = "javax.xml.bind.JAXBElement"; + private FaultExceptionMapper faultExceptionMapper; + + public JAXWSJavaInterfaceProcessor(FaultExceptionMapper faultExceptionMapper) { + super(); + this.faultExceptionMapper = faultExceptionMapper; + } + + public JAXWSJavaInterfaceProcessor() { + super(); + } + + public void visitInterface(JavaInterface contract) throws InvalidInterfaceException { + + Class clazz = contract.getJavaClass(); + //WebService webService = clazz.getAnnotation(WebService.class); + String tns = JavaInterfaceUtil.getNamespace(clazz); + //if (webService != null) { + // tns = getValue(webService.targetNamespace(), tns); + // Mark SEI as Remotable + //contract.setRemotable(true); + //} + if (!contract.isRemotable()) { + return; + } + + // SOAP binding (doc/lit/wrapped|bare or rpc/lit) + //SOAPBinding soapBinding = clazz.getAnnotation(SOAPBinding.class); + + for (Iterator it = contract.getOperations().iterator(); it.hasNext();) { + JavaOperation operation = (JavaOperation)it.next(); + Method method = operation.getJavaMethod(); + introspectFaultTypes(operation); + + // SOAP binding (doc/lit/wrapped|bare or rpc/lit) + //SOAPBinding methodSOAPBinding = method.getAnnotation(SOAPBinding.class); + //if (methodSOAPBinding == null) { + // methodSOAPBinding = soapBinding; + //} + + boolean documentStyle = true; + boolean bare = false; + //if (methodSOAPBinding != null) { + // bare = methodSOAPBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE; + // For BARE parameter style, the data is in the wrapped format already + // operation.setWrapperStyle(bare); + //documentStyle = methodSOAPBinding.style() == Style.DOCUMENT; + //} + + String operationName = operation.getName(); + // WebMethod + //WebMethod webMethod = method.getAnnotation(WebMethod.class); + //if (webMethod != null) { + // if (webMethod.exclude()) { + // Exclude the method + // it.remove(); + // continue; + //} + //operationName = getValue(webMethod.operationName(), operationName); + //operation.setName(operationName); + //} + + // Is one way? + /*Oneway oneway = method.getAnnotation(Oneway.class); + if (oneway != null) { + // JSR 181 + assert method.getReturnType() == void.class; + operation.setNonBlocking(true); + }*/ + + // Handle BARE mapping + if (bare) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + /*WebParam param = getAnnotation(method, i, WebParam.class); + if (param != null) { + String ns = getValue(param.targetNamespace(), tns); + // Default to for doc-bare + String name = getValue(param.name(), documentStyle ? operationName : "arg" + i); + QName element = new QName(ns, name); + Object logical = operation.getInputType().getLogical().get(i).getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + }*/ + } + /* WebResult result = method.getAnnotation(WebResult.class); + if (result != null) { + String ns = getValue(result.targetNamespace(), tns); + // Default to Response for doc-bare + String name = getValue(result.name(), documentStyle ? operationName + "Response" : "return"); + QName element = new QName(ns, name); + Object logical = operation.getOutputType().getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + }*/ + // FIXME: [rfeng] For the BARE mapping, do we need to create a Wrapper? + // it's null at this point + } else { + + RequestWrapper requestWrapper = method.getAnnotation(RequestWrapper.class); + String ns = requestWrapper == null ? tns : getValue(requestWrapper.targetNamespace(), tns); + String name = + requestWrapper == null ? operationName : getValue(requestWrapper.localName(), operationName); + QName inputWrapper = new QName(ns, name); + + ResponseWrapper responseWrapper = method.getAnnotation(ResponseWrapper.class); + ns = responseWrapper == null ? tns : getValue(responseWrapper.targetNamespace(), tns); + name = + responseWrapper == null ? operationName + "Response" : getValue(responseWrapper.localName(), + operationName + "Response"); + QName outputWrapper = new QName(ns, name); + + List inputElements = new ArrayList(); + for (int i = 0; i < method.getParameterTypes().length; i++) { +// WebParam param = getAnnotation(method, i, WebParam.class); + ns = /*param != null ? param.targetNamespace() :*/ ""; + // Default to "" for doc-lit-wrapped && non-header + ns = getValue(ns, documentStyle && (/*param == null || !param.header()*/ true) ? "" : tns); + name = /*param != null ? param.name() :*/ ""; + name = getValue(name, "arg" + i); + QName element = new QName(ns, name); + Object logical = operation.getInputType().getLogical().get(i).getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + inputElements.add(new ElementInfo(element, null)); + } + + List outputElements = new ArrayList(); + //WebResult result = method.getAnnotation(WebResult.class); + // Default to "" for doc-lit-wrapped && non-header + ns = /*result != null ? result.targetNamespace() :*/ ""; + ns = getValue(ns, documentStyle && (/*result == null || !result.header()*/true) ? "" : tns); + name = /*result != null ? result.name() :*/ ""; + name = getValue(name, "return"); + QName element = new QName(ns, name); + + if (operation.getOutputType() != null) { + Object logical = operation.getOutputType().getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + } + outputElements.add(new ElementInfo(element, null)); + + WrapperInfo wrapperInfo = + new WrapperInfo(JAXB_DATABINDING, new ElementInfo(inputWrapper, null), + new ElementInfo(outputWrapper, null), inputElements, outputElements); + operation.setWrapper(wrapperInfo); + } + } + } + + @SuppressWarnings("unchecked") + private void introspectFaultTypes(Operation operation) { + for (DataType exceptionType : operation.getFaultTypes()) { + faultExceptionMapper.introspectFaultDataType(exceptionType); + } + } + + private T getAnnotation(Method method, int index, Class annotationType) { + Annotation[] annotations = method.getParameterAnnotations()[index]; + for (Annotation annotation : annotations) { + if (annotation.annotationType() == annotationType) { + return annotationType.cast(annotation); + } + } + return null; + } + + private static String getValue(String value, String defaultValue) { + return "".equals(value) ? defaultValue : value; + } + +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java new file mode 100644 index 0000000000..9a31cb6127 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.interfacedef.java.jaxws; + +public interface Bean { + T getP1(); +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.java b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.java new file mode 100644 index 0000000000..b41ff14af0 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.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.interfacedef.java.jaxws; + +public class Bean1 { + private String p1; + private int p2; + public String getP1() { + return p1; + } + public void setP1(String p1) { + this.p1 = p1; + } + public int getP2() { + return p2; + } + public void setP2(int p2) { + this.p2 = p2; + } +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.java b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.java new file mode 100644 index 0000000000..34c8d2c67d --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.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.interfacedef.java.jaxws; + +public class Bean2 implements Bean{ + private String p1; + private int p2; + public String getP1() { + return p1; + } + public void setP1(String p1) { + this.p1 = p1; + } + public int getP2() { + return p2; + } + public void setP2(int p2) { + this.p2 = p2; + } +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.java b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.java new file mode 100644 index 0000000000..7e4114d854 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.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.interfacedef.java.jaxws; + +import javax.jws.WebMethod; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; + +/** + * + */ +public class JAXWSJavaInterfaceProcessorTestCase extends TestCase { + private JAXWSJavaInterfaceProcessor interfaceProcessor; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + interfaceProcessor = new JAXWSJavaInterfaceProcessor(); + } + + /** + * Test method for + * {@link org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSJavaInterfaceProcessor#visitInterface(JavaInterface)}. + */ + public final void testProcessor() throws Exception { + DefaultJavaInterfaceFactory iFactory = new DefaultJavaInterfaceFactory(); + JavaInterface contract = iFactory.createJavaInterface(WebServiceInterfaceWithoutAnnotation.class); + + interfaceProcessor.visitInterface(contract); + assertFalse(contract.isRemotable()); + + contract = iFactory.createJavaInterface(WebServiceInterfaceWithAnnotation.class); + interfaceProcessor.visitInterface(contract); + assertTrue(contract.isRemotable()); + + Operation op1 = contract.getOperations().get(0); + Operation op2 = contract.getOperations().get(1); + + Operation op = null; + if ("m1".equals(op1.getName())) { + op = op1; + } else { + op = op2; + } + + assertTrue(op.isWrapperStyle()); + + if ("M2".equals(op2.getName())) { + op = op2; + } else { + op = op1; + } + assertTrue(!op2.isWrapperStyle() && op2.getWrapper() != null); + + } + + @WebService + private static interface WebServiceInterfaceWithAnnotation { + + @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) + @WebMethod(operationName = "m1") + String m1(String str); + + @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) + @WebMethod(operationName = "M2") + String m2(String str, int i); + } + + private static interface WebServiceInterfaceWithoutAnnotation { + + } +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java new file mode 100644 index 0000000000..b0478f6c71 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +public class MyException extends Exception { + private String error; + + public MyException() { + super(); + } + + public MyException(String message, Throwable cause) { + super(message, cause); + } + + public MyException(String message) { + super(message); + } + + public MyException(Throwable cause) { + super(cause); + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java new file mode 100644 index 0000000000..9597cd892b --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.util.List; + +import javax.jws.WebMethod; +import javax.jws.WebService; + +/** + * @version $Rev: 639350 $ $Date: 2008-03-20 08:43:46 -0800 (Thu, 20 Mar 2008) $ + */ +@WebService +public class MyServiceImpl { + + public MyServiceImpl() { + super(); + } + + @WebMethod + public T getBean(T b, Bean2 b2) { + return null; + } + + @WebMethod + public List getBeans() { + return null; + } + + @WebMethod + public String convert(String str, int i) throws MyException { + return "ME"; + } + +} diff --git a/branches/sca-android/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl b/branches/sca-android/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl new file mode 100644 index 0000000000..87f75cca39 --- /dev/null +++ b/branches/sca-android/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/interface-java/.classpath b/branches/sca-android/interface-java/.classpath new file mode 100644 index 0000000000..553679d82e --- /dev/null +++ b/branches/sca-android/interface-java/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/interface-java/.project b/branches/sca-android/interface-java/.project new file mode 100644 index 0000000000..cdc464f4dd --- /dev/null +++ b/branches/sca-android/interface-java/.project @@ -0,0 +1,21 @@ + + tuscany-interface-java + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-contribution + tuscany-definitions + tuscany-extensibility + tuscany-interface + tuscany-policy + tuscany-sca-api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/interface-java/DISCLAIMER b/branches/sca-android/interface-java/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/interface-java/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/interface-java/LICENSE b/branches/sca-android/interface-java/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/interface-java/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/branches/sca-android/interface-java/NOTICE b/branches/sca-android/interface-java/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/interface-java/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/interface-java/pom.xml b/branches/sca-android/interface-java/pom.xml new file mode 100644 index 0000000000..a197b7bd77 --- /dev/null +++ b/branches/sca-android/interface-java/pom.xml @@ -0,0 +1,63 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-interface-java + Apache Tuscany SCA Java Interface Model + + + + org.apache.tuscany.sca + tuscany-extensibility + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-assembly + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-sca-api + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-incubating-SNAPSHOT + + + + diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java new file mode 100644 index 0000000000..7c4d6ea400 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceFactoryImpl; +import org.apache.tuscany.sca.interfacedef.java.impl.PolicyJavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * A factory for the Java interface model. + */ +public class DefaultJavaInterfaceFactory extends JavaInterfaceFactoryImpl implements JavaInterfaceFactory { + private ModelFactoryExtensionPoint modelFactoryExtensionPoint; + private boolean loadedVisitors; + + public DefaultJavaInterfaceFactory() { + } + + public DefaultJavaInterfaceFactory(ModelFactoryExtensionPoint modelFactoryExtensionPoint) { + this.modelFactoryExtensionPoint = modelFactoryExtensionPoint; + } + + @Override + public List getInterfaceVisitors() { + loadVisitors(); + return super.getInterfaceVisitors(); + } + + /** + * Load visitors declared under META-INF/services + */ + @SuppressWarnings("unchecked") + private void loadVisitors() { + if (loadedVisitors) + return; + + if (modelFactoryExtensionPoint != null) { + PolicyFactory policyFactory = modelFactoryExtensionPoint.getFactory(PolicyFactory.class); + if (policyFactory != null) { + addInterfaceVisitor(new PolicyJavaInterfaceVisitor(policyFactory)); + } + } + + // Get the databinding service declarations + Set visitorDeclarations; + try { + visitorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(JavaInterfaceVisitor.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Load data bindings + for (ServiceDeclaration visitorDeclaration: visitorDeclarations) { + JavaInterfaceVisitor visitor; + try { + Class visitorClass = (Class)visitorDeclaration.loadClass(); + visitor = visitorClass.newInstance(); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } catch (InstantiationException e) { + throw new IllegalArgumentException(e); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + addInterfaceVisitor(visitor); + } + + loadedVisitors = true; + } + + + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java new file mode 100644 index 0000000000..58297d3746 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.interfacedef.Interface; + +/** + * Represents a Java interface. + * + * @version $Rev: 574428 $ $Date: 2007-09-10 18:01:37 -0800 (Mon, 10 Sep 2007) $ + */ +public interface JavaInterface extends Interface, Base { + + /** + * Returns the name of the Java interface class. + * + * @return the name of the Java interface class + */ + String getName(); + + /** + * Sets the name of the Java interface class. + * + * @param className the name of the Java interface class + */ + void setName(String className); + + /** + * Returns the Java interface class. + * + * @return the Java interface class + */ + Class getJavaClass(); + + /** + * Sets the Java interface class. + * + * @param javaClass the Java interface class + */ + void setJavaClass(Class javaClass); + + /** + * Returns the callback class specified in an @Callback annotation. + * + * @return the callback class specified in an @Callback annotation + */ + Class getCallbackClass(); + + /** + * Sets the callback class specified in an @Callback annotation. + * + * @param callbackClass the callback class specified in an @Callback annotation + */ + void setCallbackClass(Class callbackClass); +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.java new file mode 100644 index 0000000000..012834afd9 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.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.interfacedef.java; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * Represents a Java interface contract. + * JavaInterfaceContract + * + * @version $Rev: 537404 $ $Date: 2007-05-12 04:51:42 -0800 (Sat, 12 May 2007) $ + */ +public interface JavaInterfaceContract extends InterfaceContract { + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java new file mode 100644 index 0000000000..0559e7c7f2 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.interfacedef.java; + +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; + +/** + * Factory for the Java interface model + * + * @version $Rev: 564364 $ $Date: 2007-08-09 12:14:52 -0800 (Thu, 09 Aug 2007) $ + */ +public interface JavaInterfaceFactory { + + /** + * Creates a new Java interface model. + * + * @return + */ + JavaInterface createJavaInterface(); + + /** + * Creates a new Java interface model from an interface class. + * @param interfaceClass the interface class to introspect. + * @return + */ + JavaInterface createJavaInterface(Class interfaceClass) throws InvalidInterfaceException; + + /** + * Creates the contents of a Java interface model from an interface class. + * @param javaInterface the Java interface model + * @param interfaceClass the interface class to introspect. + * @return + */ + void createJavaInterface(JavaInterface javaInterface, Class interfaceClass) throws InvalidInterfaceException; + + /** + * Creates a new Java interface contract. + * + * @return + */ + JavaInterfaceContract createJavaInterfaceContract(); + + /** + * Registers the given visitor. + * + * @param visitor + */ + void addInterfaceVisitor(JavaInterfaceVisitor visitor); + + /** + * Deregisters the given visitor. + * + * @param visitor + */ + void removeInterfaceVisitor(JavaInterfaceVisitor visitor); + + /** + * Returns a list of interface visitors. + * + * @return + */ + List getInterfaceVisitors(); +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java new file mode 100644 index 0000000000..e34f109272 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.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.interfacedef.java; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * Represents a Java operation. + * + * @version $Rev: 614967 $ $Date: 2008-01-24 12:00:04 -0800 (Thu, 24 Jan 2008) $ + */ +public interface JavaOperation extends Operation { + + /** + * Returns the Java method defining the operation. + * @return the Java method + */ + Method getJavaMethod(); + + /** + * Sets the Java method defining the operation. + * @param method the Java method + */ + void setJavaMethod(Method method); + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java new file mode 100644 index 0000000000..67bf167aa3 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; + +/** + * Represents a Java interface contract. + * + * @version $Rev: 557493 $ $Date: 2007-07-18 21:28:26 -0800 (Wed, 18 Jul 2007) $ + */ +public class JavaInterfaceContractImpl extends InterfaceContractImpl implements JavaInterfaceContract { + + protected JavaInterfaceContractImpl() { + } + + @Override + public JavaInterfaceContractImpl clone() throws CloneNotSupportedException { + return (JavaInterfaceContractImpl) super.clone(); + } + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java new file mode 100644 index 0000000000..79b76eaa3f --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.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.interfacedef.java.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; + +/** + * A factory for the Java model. + */ +public abstract class JavaInterfaceFactoryImpl implements JavaInterfaceFactory { + + private List visitors = new ArrayList(); + private JavaInterfaceIntrospectorImpl introspector; + + public JavaInterfaceFactoryImpl() { + introspector = new JavaInterfaceIntrospectorImpl(this); + } + + public JavaInterface createJavaInterface() { + return new JavaInterfaceImpl(); + } + + public JavaInterface createJavaInterface(Class interfaceClass) throws InvalidInterfaceException { + JavaInterface javaInterface = createJavaInterface(); + introspector.introspectInterface(javaInterface, interfaceClass); + return javaInterface; + } + + public void createJavaInterface(JavaInterface javaInterface, Class interfaceClass) throws InvalidInterfaceException { + introspector.introspectInterface(javaInterface, interfaceClass); + } + + public JavaInterfaceContract createJavaInterfaceContract() { + return new JavaInterfaceContractImpl(); + } + + public void addInterfaceVisitor(JavaInterfaceVisitor extension) { + visitors.add(extension); + } + + public void removeInterfaceVisitor(JavaInterfaceVisitor extension) { + visitors.remove(extension); + } + + public List getInterfaceVisitors() { + return visitors; + } +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java new file mode 100644 index 0000000000..0ff0e174b5 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.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.interfacedef.java.impl; + +import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; + +/** + * Represents a Java interface. + * + * @version $Rev: 639350 $ $Date: 2008-03-20 08:43:46 -0800 (Thu, 20 Mar 2008) $ + */ +public class JavaInterfaceImpl extends InterfaceImpl implements JavaInterface { + + private String className; + private Class javaClass; + private Class callbackClass; + + protected JavaInterfaceImpl() { + } + + public String getName() { + if (isUnresolved()) { + return className; + } else if (javaClass != null) { + return javaClass.getName(); + } else { + return null; + } + } + + public void setName(String className) { + if (!isUnresolved()) { + throw new IllegalStateException(); + } + this.className = className; + } + + public Class getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + } + + public Class getCallbackClass() { + return callbackClass; + } + + public void setCallbackClass(Class callbackClass) { + this.callbackClass = callbackClass; + } + + @Override + public String toString() { + return getName(); + } + + @Override + public int hashCode() { + return String.valueOf(getName()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof JavaInterface) { + if (getName() != null) { + return getName().equals(((JavaInterface)obj).getName()); + } else { + return ((JavaInterface)obj).getName() == null; + } + } else { + return false; + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java new file mode 100644 index 0000000000..a0292d3327 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +//import java.rmi.Remote; +//import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidCallbackException; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.InvalidOperationException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.OverloadedOperationException; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.osoa.sca.annotations.Conversational; +import org.osoa.sca.annotations.EndsConversation; +import org.osoa.sca.annotations.OneWay; +import org.osoa.sca.annotations.Remotable; + +/** + * Default implementation of a Java interface introspector. + * + * @version $Rev: 641897 $ $Date: 2008-03-27 09:07:00 -0800 (Thu, 27 Mar 2008) $ + */ +public class JavaInterfaceIntrospectorImpl { + public static final String IDL_INPUT = "idl:input"; + + private static final String UNKNOWN_DATABINDING = null; + + private List visitors = new ArrayList(); + + public JavaInterfaceIntrospectorImpl(JavaInterfaceFactory javaFactory) { + this.visitors = javaFactory.getInterfaceVisitors(); + } + + public void introspectInterface(JavaInterface javaInterface, Class clazz) throws InvalidInterfaceException { + javaInterface.setJavaClass(clazz); + + boolean remotable = clazz.isAnnotationPresent(Remotable.class); + + // Consider @javax.ejb.Remote, java.rmi.Remote and javax.ejb.EJBObject + // equivalent to @Remotable + if (!remotable) { + for (Annotation annotation: clazz.getAnnotations()) { + if ("javax.ejb.Remote".equals(annotation.annotationType().getName())) { + remotable = true; + break; + } + } + } + if (!remotable) { + for (Class superInterface: clazz.getInterfaces()) { + if (/*Remote.class == superInterface || */"javax.ejb.EJBObject".equals(superInterface.getName())) { + remotable = true; + break; + } + } + } + + javaInterface.setRemotable(remotable); + + boolean conversational = clazz.isAnnotationPresent(Conversational.class); + javaInterface.setConversational(conversational); + + Class callbackClass = null; + org.osoa.sca.annotations.Callback callback = clazz.getAnnotation(org.osoa.sca.annotations.Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + callbackClass = callback.value(); + } else if (callback != null && Void.class.equals(callback.value())) { + throw new InvalidCallbackException("No callback interface specified on annotation"); + } + javaInterface.setCallbackClass(callbackClass); + + String ns = JavaInterfaceUtil.getNamespace(clazz); + javaInterface.getOperations().addAll(getOperations(clazz, remotable, conversational, ns)); + + for (JavaInterfaceVisitor extension : visitors) { + extension.visitInterface(javaInterface); + } + } + + private Class[] getActualTypes(Type[] types, Class[] rawTypes, Map typeBindings) { + Class[] actualTypes = new Class[types.length]; + for (int i = 0; i < actualTypes.length; i++) { + actualTypes[i] = getActualType(types[i], rawTypes[i], typeBindings); + } + return actualTypes; + } + + private Class getActualType(Type type, Class rawType, Map typeBindings) { + if (type instanceof TypeVariable) { + TypeVariable typeVariable = (TypeVariable)type; + type = typeBindings.get(typeVariable.getName()); + if (type instanceof Class) { + return (Class)type; + } + } + return rawType; + } + + private List getOperations(Class clazz, boolean remotable, boolean conversational, String ns) + throws InvalidInterfaceException { + + Type[] genericInterfaces = clazz.getGenericInterfaces(); + Map typeBindings = new HashMap(); + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType)genericInterface; + TypeVariable[] typeVariables = ((Class)parameterizedType.getRawType()).getTypeParameters(); + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + for (int i = 0; i < typeArguments.length; i++) { + typeBindings.put(typeVariables[i].getName(), typeArguments[i]); + } + } + } + + Method[] methods = clazz.getMethods(); + List operations = new ArrayList(methods.length); + Set names = remotable ? new HashSet() : null; + for (Method method : methods) { + if (method.getDeclaringClass() == Object.class) { + // Skip the methods on the Object.class + continue; + } + String name = method.getName(); + if (remotable && names.contains(name)) { + throw new OverloadedOperationException(method); + } + if (remotable) { + names.add(name); + } + + Class returnType = getActualType(method.getGenericReturnType(), method.getReturnType(), typeBindings); + Class[] parameterTypes = + getActualTypes(method.getGenericParameterTypes(), method.getParameterTypes(), typeBindings); + Class[] faultTypes = + getActualTypes(method.getGenericExceptionTypes(), method.getExceptionTypes(), typeBindings); + + boolean nonBlocking = method.isAnnotationPresent(OneWay.class); + ConversationSequence conversationSequence = ConversationSequence.CONVERSATION_NONE; + if (method.isAnnotationPresent(EndsConversation.class)) { + if (!conversational) { + throw new InvalidOperationException( + "Method is marked as end conversation but contract is not conversational", + method); + } + conversationSequence = ConversationSequence.CONVERSATION_END; + } else if (conversational) { + conversationSequence = ConversationSequence.CONVERSATION_CONTINUE; + } + + // Set outputType to null for void + XMLType xmlReturnType = new XMLType(new QName(ns, "return"), null); + DataType returnDataType = + returnType == void.class ? null : new DataTypeImpl(UNKNOWN_DATABINDING, returnType, + xmlReturnType); + List paramDataTypes = new ArrayList(parameterTypes.length); + for (int i = 0; i < parameterTypes.length; i++) { + Class paramType = parameterTypes[i]; + XMLType xmlParamType = new XMLType(new QName(ns, "arg" + i), null); + paramDataTypes.add(new DataTypeImpl(UNKNOWN_DATABINDING, paramType, xmlParamType)); + } + List faultDataTypes = new ArrayList(faultTypes.length); + for (Class faultType : faultTypes) { + // Only add checked exceptions + // JAXWS Specification v2.1 section 3.7 says RemoteException should not be mapped + if (Exception.class.isAssignableFrom(faultType) && (!RuntimeException.class.isAssignableFrom(faultType)) + /*&& (!RemoteException.class.isAssignableFrom(faultType))*/) { + XMLType xmlFaultType = new XMLType(new QName(ns, faultType.getSimpleName()), null); + DataType faultDataType = new DataTypeImpl(faultType, xmlFaultType); + faultDataTypes.add(new DataTypeImpl(UNKNOWN_DATABINDING, faultType, faultDataType)); + } + } + + DataType> inputType = + new DataTypeImpl>(IDL_INPUT, Object[].class, paramDataTypes); + JavaOperation operation = new JavaOperationImpl(); + operation.setName(name); + operation.setInputType(inputType); + operation.setOutputType(returnDataType); + operation.setFaultTypes(faultDataTypes); + operation.setConversationSequence(conversationSequence); + operation.setNonBlocking(nonBlocking); + operation.setJavaMethod(method); + operations.add(operation); + } + return operations; + } + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java new file mode 100644 index 0000000000..328fc38ee9 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; + +/** + * Contains methods for mapping between an operation in a + * {@link org.apache.tuscany.spi.model.ServiceContract} and a method defined by + * a Java interface + * + * @version $Rev: 634877 $ $Date: 2008-03-07 16:45:07 -0800 (Fri, 07 Mar 2008) $ + */ +public final class JavaInterfaceUtil { + + private JavaInterfaceUtil() { + } + + /** + * Return the method on the implementation class that matches the operation. + * + * @param implClass the implementation class or interface + * @param operation the operation to match + * @return the method described by the operation + * @throws NoSuchMethodException if no such method exists + * @Deprecated + */ + public static Method findMethod(Class implClass, Operation operation) throws NoSuchMethodException { + String name = operation.getName(); + if (operation instanceof JavaOperation) { + name = ((JavaOperation)operation).getJavaMethod().getName(); + } + Interface interface1 = operation.getInterface(); + if (interface1 != null && interface1.isRemotable()) { + for (Method m : implClass.getMethods()) { + if (m.getName().equals(name)) { + return m; + } + } + throw new NoSuchMethodException("No matching method for operation " + operation.getName() + + " is found on " + + implClass); + } + Class[] paramTypes = getPhysicalTypes(operation); + return implClass.getMethod(name, paramTypes); + } + + /** + * @Deprecated + */ + private static Class[] getPhysicalTypes(Operation operation) { + DataType> inputType = operation.getInputType(); + if (inputType == null) { + return new Class[] {}; + } + List types = inputType.getLogical(); + Class[] javaTypes = new Class[types.size()]; + for (int i = 0; i < javaTypes.length; i++) { + Type physical = types.get(i).getPhysical(); + if (physical instanceof Class) { + javaTypes[i] = (Class)physical; + } else { + throw new UnsupportedOperationException(); + } + } + return javaTypes; + } + + /** + * Searches a collection of operations for a match against the given method + * + * @param method the method to match + * @param operations the operations to match against + * @return a matching operation or null + * @Deprecated + */ + public static Operation findOperation(Method method, Collection operations) { + for (Operation operation : operations) { + if (match(operation, method)) { + return operation; + } + } + return null; + } + + /** + * Determines if the given operation matches the given method + * + * @return true if the operation matches, false if does not + */ + private static boolean match(Operation operation, Method method) { + Class[] params = method.getParameterTypes(); + DataType> inputType = operation.getInputType(); + List types = inputType.getLogical(); + boolean found = true; + if (types.size() == params.length && method.getName().equals(operation.getName())) { + for (int i = 0; i < params.length; i++) { + Class clazz = params[i]; + if (!clazz.equals(operation.getInputType().getLogical().get(i).getPhysical())) { + found = false; + } + } + } else { + found = false; + } + return found; + + } + + public static String getNamespace(Class cls) { + Package pkg = cls.getPackage(); + if (pkg == null) { + return ""; + } + StringBuffer ns = new StringBuffer("http://"); + String[] names = pkg.getName().split("\\."); + for (int i = names.length - 1; i >= 0; i--) { + ns.append(names[i]); + if (i != 0) { + ns.append('.'); + } + } + ns.append('/'); + return ns.toString(); + } + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java new file mode 100644 index 0000000000..6853f7931d --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; + +/** + * Represents a Java operation. + * + * @version $Rev: 616060 $ $Date: 2008-01-28 13:39:55 -0800 (Mon, 28 Jan 2008) $ + */ +public class JavaOperationImpl extends OperationImpl implements JavaOperation { + + private Method method; + + public Method getJavaMethod() { + return method; + } + + public void setJavaMethod(Method method) { + this.method = method; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + final JavaOperationImpl other = (JavaOperationImpl)obj; + if (method == null) { + if (other.method != null) + return false; + } else if (!method.equals(other.method)) + return false; + return true; + } + + public String toString() { + return method == null ? "null" : method.toGenericString(); + } + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java new file mode 100644 index 0000000000..cba865593d --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.osoa.sca.annotations.PolicySets; +import org.osoa.sca.annotations.Requires; + +/** + * Processes an {@link org.osoa.sca.annotations.Requires} annotation + * + * @version $Rev: + */ +public class PolicyJavaInterfaceVisitor implements JavaInterfaceVisitor { + private PolicyFactory policyFactory; + + public PolicyJavaInterfaceVisitor(PolicyFactory policyFactory) { + super(); + this.policyFactory = policyFactory; + } + + private QName getQName(String intentName) { + QName qname; + if (intentName.startsWith("{")) { + int i = intentName.indexOf('}'); + if (i != -1) { + qname = new QName(intentName.substring(1, i), intentName.substring(i + 1)); + } else { + qname = new QName("", intentName); + } + } else { + qname = new QName("", intentName); + } + return qname; + } + + /** + * Read policy intents on the given interface or class + * @param clazz + * @param requiredIntents + */ + private void readIntentsAndPolicySets(Class clazz, List requiredIntents, List policySets) { + Requires intentAnnotation = clazz.getAnnotation(Requires.class); + if (intentAnnotation != null) { + String[] intentNames = intentAnnotation.value(); + if (intentNames.length != 0) { + for (String intentName : intentNames) { + + // Add each intent to the list + Intent intent = policyFactory.createIntent(); + intent.setName(getQName(intentName)); + requiredIntents.add(intent); + } + } + } + + PolicySets policySetAnnotation = clazz.getAnnotation(PolicySets.class); + if (policySetAnnotation != null) { + String[] policySetNames = policySetAnnotation.value(); + if (policySetNames.length != 0) { + for (String policySetName : policySetNames) { + + // Add each intent to the list + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(getQName(policySetName)); + policySets.add(policySet); + } + } + } + } + + private void readIntents(Requires intentAnnotation, List requiredIntents) { + //Requires intentAnnotation = method.getAnnotation(Requires.class); + if (intentAnnotation != null) { + String[] intentNames = intentAnnotation.value(); + if (intentNames.length != 0) { + //Operation operation = assemblyFactory.createOperation(); + //operation.setName(method.getName()); + //operation.setUnresolved(true); + for (String intentName : intentNames) { + + // Add each intent to the list, associated with the + // operation corresponding to the annotated method + Intent intent = policyFactory.createIntent(); + intent.setName(getQName(intentName)); + //intent.getOperations().add(operation); + requiredIntents.add(intent); + } + } + } + } + + private void readPolicySets(PolicySets policySetAnnotation, List policySets) { + if (policySetAnnotation != null) { + String[] policySetNames = policySetAnnotation.value(); + if (policySetNames.length != 0) { + //Operation operation = assemblyFactory.createOperation(); + //operation.setName(method.getName()); + //operation.setUnresolved(true); + for (String policySetName : policySetNames) { + // Add each intent to the list, associated with the + // operation corresponding to the annotated method + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(getQName(policySetName)); + //intent.getOperations().add(operation); + policySets.add(policySet); + } + } + } + } + + public void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException { + + if (javaInterface.getJavaClass() != null) { + readIntentsAndPolicySets(javaInterface.getJavaClass(), javaInterface.getRequiredIntents(), javaInterface + .getPolicySets()); + + // Read intents on the service interface methods + List operations = javaInterface.getOperations(); + for (Operation op : operations) { + JavaOperation operation = (JavaOperation)op; + Method method = operation.getJavaMethod(); + if (method.getAnnotation(Requires.class) != null || method.getAnnotation(PolicySets.class) != null) { + readIntents(method.getAnnotation(Requires.class), op.getRequiredIntents()); + readPolicySets(method.getAnnotation(PolicySets.class), op.getPolicySets()); + } + } + } + } + +} diff --git a/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java new file mode 100644 index 0000000000..49f019a9d2 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspect; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; + +/** + * Implementations introspect metadata on a Java interface, populating the + * corresponding {@link JavaInterface} + * + * @version $Rev: 537404 $ $Date: 2007-05-12 04:51:42 -0800 (Sat, 12 May 2007) $ + */ +public interface JavaInterfaceVisitor { + + /** + * Visit a java interface + * @param javaInterface + * @throws InvalidInterfaceException + */ + void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException; + +} diff --git a/branches/sca-android/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory b/branches/sca-android/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory new file mode 100644 index 0000000000..5ba12ec137 --- /dev/null +++ b/branches/sca-android/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory @@ -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.interfacedef.java.DefaultJavaInterfaceFactory \ No newline at end of file diff --git a/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.java b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.java new file mode 100644 index 0000000000..d86c029863 --- /dev/null +++ b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.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.interfacedef.java.impl; + +import static org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil.findOperation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; + +/** + * @version $Rev: 614967 $ $Date: 2008-01-24 12:00:04 -0800 (Thu, 24 Jan 2008) $ + */ +public class JavaInterfaceUtilTestCase extends TestCase { + private List operations; + + public void testNoParamsFindOperation() throws Exception { + Method method = Foo.class.getMethod("foo"); + Operation ret = findOperation(method, operations); + assertEquals("foo", ret.getName()); + assertEquals(0, method.getParameterTypes().length); + } + + public void testParamsFindOperation() throws Exception { + Method method = Foo.class.getMethod("foo", String.class); + Operation ret = findOperation(method, operations); + assertEquals("foo", ret.getName()); + assertEquals(String.class, method.getParameterTypes()[0]); + } + + public void testPrimitiveParamFindOperation() throws NoSuchMethodException { + Method method = Foo.class.getMethod("foo", Integer.TYPE); + Operation operation = findOperation(method, operations); + assertEquals(Integer.TYPE, operation.getInputType().getLogical().get(0).getPhysical()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + Operation operation = newOperation("foo"); + List types = new ArrayList(); + DataType> inputType = new DataTypeImpl>(Object[].class, types); + operation.setInputType(inputType); + + operations = new ArrayList(); + operations.add(operation); + + types = new ArrayList(); + inputType = new DataTypeImpl>(Object[].class, types); + DataType type = new DataTypeImpl(String.class, Object.class); + types.add(type); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + types = new ArrayList(); + type = new DataTypeImpl(String.class, Object.class); + DataType type2 = new DataTypeImpl(String.class, Object.class); + types.add(type); + types.add(type2); + inputType = new DataTypeImpl>(Object[].class, types); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + types = new ArrayList(); + type = new DataTypeImpl(Integer.class, Object.class); + types.add(type); + inputType = new DataTypeImpl>(Object[].class, types); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + types = new ArrayList(); + type = new DataTypeImpl(Integer.TYPE, Object.class); + types.add(type); + inputType = new DataTypeImpl>(Object[].class, types); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + } + + private interface Foo { + void foo(); + + void foo(String foo); + + void foo(int b); + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} diff --git a/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.java b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.java new file mode 100644 index 0000000000..62c1105d50 --- /dev/null +++ b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.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.interfacedef.java.introspection.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InvalidOperationException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.annotations.Conversational; +import org.osoa.sca.annotations.EndsConversation; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 21:13:29 -0800 (Sun, 19 Aug 2007) $ + */ +public class ConversationalIntrospectionTestCase extends TestCase { + private JavaInterfaceFactory javaFactory; + + @Override + protected void setUp() throws Exception { + javaFactory = new DefaultJavaInterfaceFactory(); + } + + private Operation getOperation(Interface i, String name) { + for (Operation op : i.getOperations()) { + if (op.getName().equals(name)) { + return op; + } + } + return null; + } + + public void testServiceContractConversationalInformationIntrospection() throws Exception { + Interface i = javaFactory.createJavaInterface(Foo.class); + assertNotNull(i); + assertTrue(i.isConversational()); + ConversationSequence seq = getOperation(i, "operation").getConversationSequence(); + assertEquals(ConversationSequence.CONVERSATION_CONTINUE, seq); + seq = getOperation(i, "endOperation").getConversationSequence(); + assertEquals(ConversationSequence.CONVERSATION_END, seq); + } + + public void testBadServiceContract() throws Exception { + try { + javaFactory.createJavaInterface(BadFoo.class); + fail(); + } catch (InvalidOperationException e) { + // expected + } + } + + public void testNonConversationalInformationIntrospection() throws Exception { + Interface i = javaFactory.createJavaInterface(NonConversationalFoo.class); + assertFalse(i.isConversational()); + ConversationSequence seq = getOperation(i, "operation") + .getConversationSequence(); + assertEquals(ConversationSequence.CONVERSATION_NONE, seq); + } + + @Conversational + private interface Foo { + void operation(); + + @EndsConversation + void endOperation(); + } + + private interface BadFoo { + void operation(); + + @EndsConversation + void endOperation(); + } + + private interface NonConversationalFoo { + void operation(); + } + +} diff --git a/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java new file mode 100644 index 0000000000..d230b55fa3 --- /dev/null +++ b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspection.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.io.IOException; +import java.util.List; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.easymock.EasyMock; + +/** + * @version $Rev: 629687 $ $Date: 2008-02-20 20:11:14 -0800 (Wed, 20 Feb 2008) $ + */ +public class JavaInterfaceProcessorRegistryImplTestCase extends TestCase { + private JavaInterfaceFactory factory; + + @SuppressWarnings("unchecked") + public void testSimpleInterface() throws InvalidInterfaceException { + JavaInterface intf = factory.createJavaInterface(Simple.class); + + assertEquals(Simple.class, intf.getJavaClass()); + List operations = intf.getOperations(); + assertEquals(1, operations.size()); + Operation baseInt = operations.get(0); + assertEquals("baseInt", baseInt.getName()); + + QName element = new QName("http://impl.introspection.java.interfacedef.sca.tuscany.apache.org/", "return"); + + DataType returnType = baseInt.getOutputType(); + assertEquals(Integer.TYPE, returnType.getPhysical()); + assertEquals(element, returnType.getLogical().getElementName()); + + List parameterTypes = baseInt.getInputType().getLogical(); + assertEquals(1, parameterTypes.size()); + DataType arg0 = parameterTypes.get(0); + assertEquals(Integer.TYPE, arg0.getPhysical()); + + element = new QName("http://impl.introspection.java.interfacedef.sca.tuscany.apache.org/", "arg0"); + assertEquals(element, arg0.getLogical().getElementName()); + + List faultTypes = baseInt.getFaultTypes(); + assertEquals(1, faultTypes.size()); + DataType> fault0 = faultTypes.get(0); + assertEquals(IOException.class, fault0.getPhysical()); + element = new QName("http://impl.introspection.java.interfacedef.sca.tuscany.apache.org/", "IOException"); + assertEquals(element, fault0.getLogical().getLogical().getElementName()); + } + + public void testUnregister() throws Exception { + JavaInterfaceVisitor extension = createMock(JavaInterfaceVisitor.class); + extension.visitInterface(EasyMock.isA(JavaInterface.class)); + expectLastCall().once(); + replay(extension); + factory.addInterfaceVisitor(extension); + factory.createJavaInterface(Base.class); + factory.removeInterfaceVisitor(extension); + factory.createJavaInterface(Base.class); + verify(extension); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + factory = new DefaultJavaInterfaceFactory(); + + } + + private static interface Base { + int baseInt(int param) throws IllegalArgumentException, IOException; + } + + private static interface Simple extends Base { + + } +} diff --git a/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java new file mode 100644 index 0000000000..71e4fb3cf4 --- /dev/null +++ b/branches/sca-android/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspection.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.impl.PolicyJavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.osoa.sca.annotations.PolicySets; +import org.osoa.sca.annotations.Requires; + +/** + * @version $Rev: 639350 $ $Date: 2008-03-20 08:43:46 -0800 (Thu, 20 Mar 2008) $ + */ +public class PolicyProcessorTestCase extends TestCase { + private JavaInterfaceFactory factory = new DefaultJavaInterfaceFactory(); + private PolicyJavaInterfaceVisitor policyProcessor; + + public void testInterfaceLevel() throws Exception { + JavaInterface type = factory.createJavaInterface(Interface1.class); + policyProcessor.visitInterface(type); + assertEquals(1, type.getRequiredIntents().size()); + assertEquals(1, type.getPolicySets().size()); + } + + public void testMethodLevel() throws Exception { + JavaInterface type = factory.createJavaInterface(Interface2.class); + policyProcessor.visitInterface(type); + assertEquals(0, type.getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(0).getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(1).getRequiredIntents().size()); + assertEquals(0, type.getPolicySets().size()); + assertEquals(1, type.getOperations().get(0).getPolicySets().size()); + assertEquals(1, type.getOperations().get(1).getPolicySets().size()); + } + + public void testInterfaceAndMethodLevel() throws Exception { + JavaInterface type = factory.createJavaInterface(Interface3.class); + policyProcessor.visitInterface(type); + assertEquals(1, type.getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(0).getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(1).getRequiredIntents().size()); + assertEquals(1, type.getPolicySets().size()); + assertEquals(1, type.getOperations().get(0).getPolicySets().size()); + assertEquals(1, type.getOperations().get(1).getPolicySets().size()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + policyProcessor = new PolicyJavaInterfaceVisitor(new DefaultPolicyFactory()); + } + + // @Remotable + @Requires( {"transaction.global"}) + @PolicySets( {"{http://ns1}PS1"}) + private interface Interface1 { + int method1(); + + int method2(); + + int method3(); + + int method4(); + } + + private interface Interface2 { + @Requires( {"transaction.global"}) + @PolicySets( {"{http://ns1}PS1"}) + int method1(); + + @Requires( {"transaction.local"}) + @PolicySets( {"{http://ns1}PS2"}) + int method2(); + } + + @Requires( {"transaction.global.Interface6"}) + @PolicySets( {"{http://ns1}PS1"}) + private interface Interface3 { + @Requires( {"transaction.global.Interface6.method1"}) + @PolicySets( {"{http://ns1}PS2"}) + int method1(); + + @Requires( {"transaction.local.Interface6.method2"}) + @PolicySets( {"{http://ns1}PS3"}) + int method2(); + } + +} diff --git a/branches/sca-android/retrotranslator_readme b/branches/sca-android/retrotranslator_readme new file mode 100644 index 0000000000..93e1a611cc --- /dev/null +++ b/branches/sca-android/retrotranslator_readme @@ -0,0 +1,85 @@ +Google Summer of Code 2008 +Allow Google Android applications to easily consume business services +===================================================================== +This readme details the steps necessary to run retrotranslator on a workspace hosting SCA modules and modified Android modules. + +1. Download the modified code from: https://svn.apache.org/repos/asf/incubator/tuscany/sandbox/mobile-android + +svn checkout https://svn.apache.org/repos/asf/incubator/tuscany/sandbox/mobile-android + +2. Download and install the SCA modules from: https://svn.apache.org/repos/asf/incubator/tuscany/java/sca/modules + +svn checkout --revision 643746 https://svn.apache.org/repos/asf/incubator/tuscany/java/sca/modules + +cd modules + +mvn clean install -Dtest=no +mvn -Peclipse eclipse:eclipse -Dtest=no + +3. Run maven on interface-java-jaxws module: + +cd mobile-android/interface-java-jaxws/ + +mvn + +4. Create a new Eclipse workspace and set the M2_REPO variable as shown below: + +mvn -Declipse.workspace=workspace eclipse:add-maven-repo + +5. Import the projects from step 1, making sure to uncheck the option to copy projects into the workspace. + +6. Set the Android plugin's preferences to point to the folder /tools/adb inside the SDK folder + +7. Check if the Android library was created on your eclipse user libraries. If it wasn't, create a library called "Android" and add the android-sdk/android.jar file to it. + +8. Import the projects from step 2, making sure to uncheck the option to copy projects into the workspace. + +9. Add the android.jar to android-jdk-classes + +10. Fix build path entries for JAR's displaying errors on calculator-android: + +activation-1.1.jar +axiom-api-1.2.5.jar +cgilib-nodep-2.1_3.jar +geronimo-commonj_1.1_spec-1.0.jar +stax-1.2.0.jar +stax-api-1.0-2.jar + +11. Do the same for JAR's on tuscany-host-embedded + +stax-1.2.0.jar +android.jar + +12. Add android.jar to the following modules: + +tuscany-core +tuscany-binding-ejb +tuscany-binding-http +tuscany-binding-jsonrpc +tuscany-binding-rmi +tuscany-binding-rss-rome +tuscany-binding-ws-axis2 +tuscany-contribution-groovy +tuscany-host-webapp +tuscany-implementation-das +tuscany-implementation-data-xml +tuscany-implementation-node-runtime +tuscany-implementation-osgi +tuscany-implementation-resource +tuscany-implementation-spring +tuscany-implementation-widget +tuscany-workspace-admin + +13. Build workspace + +14. Disable the "Java Builder" from all projects + +15. Run retrotranslator on mobile-android and modules from the code downloaded in steps 1 and 2, as shown below: + +java -jar ../Retrotranslator-1.2.6-bin/retrotranslator-transformer-1.2.6.jar -srcdir ../srcdir -target 1.5 -reflection safe -stripannot -embed . -classpath ../Retrotranslator-1.2.6-bin/retrotranslator-android-1.2.6.jar -verbose + +16. Add retrotranslator-android-1.2.6.jar as an external JAR to calculator-android + +17. Rebuild workspace + +18. Run calculator-android. The result will be a ClassNotFoundException for java.rmi.Remote or java.beans.Introspector \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly-xml/.classpath b/branches/sca-android/tuscany-assembly-xml/.classpath new file mode 100644 index 0000000000..3f660b27c9 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/.classpath @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly-xml/.project b/branches/sca-android/tuscany-assembly-xml/.project new file mode 100644 index 0000000000..975169eed5 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/.project @@ -0,0 +1,30 @@ + + tuscany-assembly-xml + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-assembly-xsd + tuscany-contribution + tuscany-contribution-impl + tuscany-contribution-xml + tuscany-contribution-java + tuscany-core-spi + tuscany-sca-api + tuscany-contribution-namespace + tuscany-contribution-resource + tuscany-definitions-xml + tuscany-policy-xml + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly-xml/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-assembly-xml/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..33e67d2469 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:20:00 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-assembly-xml/DISCLAIMER b/branches/sca-android/tuscany-assembly-xml/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-assembly-xml/LICENSE b/branches/sca-android/tuscany-assembly-xml/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/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/branches/sca-android/tuscany-assembly-xml/NOTICE b/branches/sca-android/tuscany-assembly-xml/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-assembly-xml/pom.xml b/branches/sca-android/tuscany-assembly-xml/pom.xml new file mode 100644 index 0000000000..1580311fff --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/pom.xml @@ -0,0 +1,116 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-assembly-xml + Apache Tuscany SCA XML Assembly Model + + + + org.apache.tuscany.sca + tuscany-assembly + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-definitions-xml + 2.0-incubating-SNAPSHOT + test + + + + org.apache.tuscany.sca + tuscany-definitions + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-namespace + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution-impl + 2.0-incubating-SNAPSHOT + test + + + + org.apache.tuscany.sca + tuscany-policy + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-policy-xml + 2.0-incubating-SNAPSHOT + test + + + + stax + stax-api + 1.0.1 + + + + org.codehaus.woodstox + wstx-asl + 3.2.1 + runtime + + + + xalan + xalan + 2.7.0 + + + + org.apache.tuscany.sca + tuscany-assembly-xsd + 2.0-incubating-SNAPSHOT + test + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java new file mode 100644 index 0000000000..b94d9e0927 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/BaseAssemblyProcessor.java @@ -0,0 +1,814 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI; +import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.dom.DOMSource; + +import org.apache.tuscany.sca.assembly.AbstractContract; +import org.apache.tuscany.sca.assembly.AbstractProperty; +import org.apache.tuscany.sca.assembly.AbstractReference; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.impl.IntentAttachPointTypeFactoryImpl; +import org.apache.tuscany.sca.policy.util.PolicyValidationException; +import org.apache.tuscany.sca.policy.util.PolicyValidationUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * A base class with utility methods for the other artifact processors in this module. + * + * @version $Rev: 643489 $ $Date: 2008-04-01 10:06:42 -0800 (Tue, 01 Apr 2008) $ + */ +abstract class BaseAssemblyProcessor extends BaseStAXArtifactProcessor implements Constants { + + protected ContributionFactory contributionFactory; + protected AssemblyFactory assemblyFactory; + protected PolicyFactory policyFactory; + protected StAXArtifactProcessor extensionProcessor; + protected PolicyAttachPointProcessor policyProcessor; + private DocumentBuilderFactory documentBuilderFactory; + protected IntentAttachPointTypeFactory intentAttachPointTypeFactory; + + /** + * Constructs a new BaseArtifactProcessor. + * @param contribFactory + * @param factory + * @param policyFactory + */ + @SuppressWarnings("unchecked") + public BaseAssemblyProcessor(ContributionFactory contribFactory, + AssemblyFactory factory, + PolicyFactory policyFactory, + StAXArtifactProcessor extensionProcessor) { + this.assemblyFactory = factory; + this.policyFactory = policyFactory; + this.extensionProcessor = (StAXArtifactProcessor)extensionProcessor; + this.contributionFactory = contribFactory; + this.policyProcessor = new PolicyAttachPointProcessor(policyFactory); + this.intentAttachPointTypeFactory = new IntentAttachPointTypeFactoryImpl(); + } + + /** + * Constructs a new BaseArtifactProcessor. + * @param factory + * @param policyFactory + */ + @SuppressWarnings("unchecked") + public BaseAssemblyProcessor(AssemblyFactory factory, + PolicyFactory policyFactory, + StAXArtifactProcessor extensionProcessor) { + this.assemblyFactory = factory; + this.policyFactory = policyFactory; + this.extensionProcessor = (StAXArtifactProcessor)extensionProcessor; + this.policyProcessor = new PolicyAttachPointProcessor(policyFactory); + } + + /** + * Start an element. + * @param writer + * @param name + * @param attrs + * @throws XMLStreamException + */ + protected void writeStart(XMLStreamWriter writer, String name, XAttr... attrs) throws XMLStreamException { + writeStart(writer, SCA10_NS, name, attrs); + } + + /** + * Start a document. + * @param writer + * @throws XMLStreamException + */ + protected void writeStartDocument(XMLStreamWriter writer, String name, XAttr... attrs) throws XMLStreamException { + writer.writeStartDocument(); + writer.setDefaultNamespace(SCA10_NS); + writeStart(writer, SCA10_NS, name, attrs); + writer.writeDefaultNamespace(SCA10_NS); + } + + /** + * Read list of reference targets + * @param reference + * @param reader + */ + protected void readTargets(Reference reference, XMLStreamReader reader) { + String value = reader.getAttributeValue(null, TARGET); + ComponentService target = null; + if (value != null) { + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + target = assemblyFactory.createComponentService(); + target.setUnresolved(true); + target.setName(tokens.nextToken()); + reference.getTargets().add(target); + } + } + } + + /** + * Write a list of targets into an attribute + * @param reference + * @return + */ + protected XAttr writeTargets(Reference reference) { + List targets = new ArrayList(); + for (Service target : reference.getTargets()) { + targets.add(target.getName()); + } + return new XAttr(TARGET, targets); + } + + /** + * Read a multiplicity attribute. + * @param reference + * @param reader + */ + protected void readMultiplicity(AbstractReference reference, XMLStreamReader reader) { + String value = reader.getAttributeValue(null, MULTIPLICITY); + if (ZERO_ONE.equals(value)) { + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } else if (ONE_N.equals(value)) { + reference.setMultiplicity(Multiplicity.ONE_N); + } else if (ZERO_N.equals(value)) { + reference.setMultiplicity(Multiplicity.ZERO_N); + } + } + + /** + * Returns the value of a constrainingType attribute. + * @param reader + * @return + */ + protected ConstrainingType readConstrainingType(XMLStreamReader reader) { + QName constrainingTypeName = getQName(reader, Constants.CONSTRAINING_TYPE); + if (constrainingTypeName != null) { + ConstrainingType constrainingType = assemblyFactory.createConstrainingType(); + constrainingType.setName(constrainingTypeName); + constrainingType.setUnresolved(true); + return constrainingType; + } else { + return null; + } + } + + /** + * Reads an abstract property element. + * @param property + * @param reader + * @throws XMLStreamException + * @throws ContributionReadException + */ + protected void readAbstractProperty(AbstractProperty property, XMLStreamReader reader) throws XMLStreamException, + ContributionReadException { + + property.setName(getString(reader, NAME)); + property.setMany(getBoolean(reader, MANY)); + property.setMustSupply(getBoolean(reader, MUST_SUPPLY)); + property.setXSDElement(getQName(reader, ELEMENT)); + property.setXSDType(getQName(reader, TYPE)); + } + + /** + * Resolve an implementation. + * @param implementation + * @param resolver + * @return + * @throws ContributionResolveException + */ + protected Implementation resolveImplementation(Implementation implementation, ModelResolver resolver) + throws ContributionResolveException, PolicyValidationException { + if (implementation != null) { + if (implementation.isUnresolved()) { + implementation = resolver.resolveModel(Implementation.class, implementation); + + // Lazily resolve implementations + if (implementation.isUnresolved()) { + extensionProcessor.resolve(implementation, resolver); + if (!implementation.isUnresolved()) { + //resolve policies + if ( implementation instanceof PolicySetAttachPoint ) { + PolicySetAttachPoint policiedImpl = (PolicySetAttachPoint)implementation; + resolveIntents(policiedImpl.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(policiedImpl, policiedImpl.getType()); + + resolvePolicySets(policiedImpl.getPolicySets(), resolver); + PolicyValidationUtils.validatePolicySets(policiedImpl); + + if ( implementation instanceof OperationsConfigurator ) { + OperationsConfigurator opsConfigurator = (OperationsConfigurator)implementation; + for ( ConfiguredOperation implOp : opsConfigurator.getConfiguredOperations() ) { + resolveIntents(implOp.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(implOp, policiedImpl.getType()); + + resolvePolicySets(implOp.getPolicySets(), resolver); + PolicyValidationUtils.validatePolicySets(implOp, + policiedImpl.getType(), + policiedImpl.getApplicablePolicySets()); + } + } + + for ( Service service : implementation.getServices() ) { + resolveIntents(service.getRequiredIntents(), resolver); + resolvePolicySets(service.getPolicySets(), resolver); + + for ( ConfiguredOperation svcOp : service.getConfiguredOperations() ) { + resolveIntents(svcOp.getRequiredIntents(), resolver); + resolvePolicySets(svcOp.getPolicySets(), resolver); + } + } + + for ( Reference reference : implementation.getReferences() ) { + resolveIntents(reference.getRequiredIntents(), resolver); + resolvePolicySets(reference.getPolicySets(), resolver); + } + } + + resolver.addModel(implementation); + } + } + } + + if ( implementation instanceof IntentAttachPoint && + ((IntentAttachPoint)implementation).getType() != null && + ((IntentAttachPoint)implementation).getType().isUnresolved() ) { + ((IntentAttachPoint)implementation).setType( + resolver.resolveModel(IntentAttachPointType.class, + ((IntentAttachPoint)implementation).getType())); + } + } + return implementation; + } + + /** + * Resolve interface, callback interface and bindings on a list of contracts. + * @param contracts the list of contracts + * @param resolver the resolver to use to resolve models + */ + protected void resolveContracts(List contracts, ModelResolver resolver) + throws ContributionResolveException { + resolveContracts(null, contracts, resolver); + } + + + /** + * Resolve interface, callback interface and bindings on a list of contracts. + * @param parent element for the contracts + * @param contracts the list of contracts + * @param resolver the resolver to use to resolve models + */ + protected void resolveContracts(Base parent, List contracts, ModelResolver resolver) + throws ContributionResolveException { + + String parentName = (parent instanceof Composite) ? ((Composite)parent).getName().toString() : + (parent instanceof Component) ? ((Component)parent).getName().toString() : "UNKNOWN"; + + for (Contract contract : contracts) { + try { + //resolve the intents and policysets as they need to be copied over into the + //child binding elements + resolveIntents(contract.getRequiredIntents(), resolver); + resolvePolicySets(contract.getPolicySets(), resolver); + resolvePolicySets(contract.getApplicablePolicySets(), resolver); + + //inherit the composite / component level policy intents and policysets + if ( parent != null && parent instanceof PolicySetAttachPoint ) { + addInheritedIntents(((PolicySetAttachPoint)parent).getRequiredIntents(), contract.getRequiredIntents()); + addInheritedPolicySets(((PolicySetAttachPoint)parent).getPolicySets(), contract.getPolicySets()); + addInheritedPolicySets(((PolicySetAttachPoint)parent).getApplicablePolicySets(), contract.getApplicablePolicySets()); + } + + for ( ConfiguredOperation confOp : contract.getConfiguredOperations() ) { + resolveIntents(confOp.getRequiredIntents(), resolver); + resolvePolicySets(confOp.getPolicySets(), resolver); + resolvePolicySets(confOp.getApplicablePolicySets(), resolver); + + //inherit intents and policysets from parent contract + addInheritedIntents(contract.getRequiredIntents(), confOp.getRequiredIntents()); + addInheritedPolicySets(contract.getPolicySets(), confOp.getPolicySets()); + addInheritedPolicySets(contract.getApplicablePolicySets(), confOp.getApplicablePolicySets()); + } + + // Resolve the interface contract + InterfaceContract interfaceContract = contract.getInterfaceContract(); + if (interfaceContract != null) { + extensionProcessor.resolve(interfaceContract, resolver); + } + + // Resolve bindings + for (int i = 0, n = contract.getBindings().size(); i < n; i++) { + Binding binding = contract.getBindings().get(i); + extensionProcessor.resolve(binding, resolver); + + if (binding instanceof IntentAttachPoint) { + IntentAttachPoint policiedBinding = (IntentAttachPoint)binding; + + if ( policiedBinding.getType().isUnresolved() ) { + IntentAttachPointType resolved = + resolver.resolveModel(IntentAttachPointType.class, + policiedBinding.getType()); + policiedBinding.setType(resolved); + } + + resolveIntents(policiedBinding.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(policiedBinding, policiedBinding.getType()); + } + + if (binding instanceof PolicySetAttachPoint) { + PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)binding; + resolvePolicySets(policiedBinding.getPolicySets(), resolver); + //validate if attached policysets apply to the binding + resolvePolicySets(policiedBinding.getApplicablePolicySets(), resolver); + //inherit the applicable policysets from parent contract as whatever applies to that + //applies to the binding as well + addInheritedPolicySets(contract.getApplicablePolicySets(), policiedBinding.getApplicablePolicySets()); + PolicyValidationUtils.validatePolicySets(policiedBinding); + } + + if (binding instanceof OperationsConfigurator) { + OperationsConfigurator opConfigurator = (OperationsConfigurator)binding; + for (ConfiguredOperation confOp : opConfigurator.getConfiguredOperations()) { + resolveIntents(confOp.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(confOp, ((PolicySetAttachPoint)binding).getType()); + + resolvePolicySets(confOp.getPolicySets(), resolver); + resolvePolicySets(confOp.getApplicablePolicySets(), resolver); + //inherit the applicable policysets from parent binding as whatever applies to that + //applies to the binding as well + addInheritedPolicySets(((PolicySetAttachPoint)binding).getApplicablePolicySets(), + confOp.getApplicablePolicySets()); + PolicyValidationUtils.validatePolicySets(confOp, ((PolicySetAttachPoint)binding).getType()); + + addInheritedIntents(((PolicySetAttachPoint)binding).getRequiredIntents(), + confOp.getRequiredIntents()); + addInheritedPolicySets(((PolicySetAttachPoint)binding).getPolicySets(), + confOp.getPolicySets()); + } + } + } + + // Resolve callback bindings + if (contract.getCallback() != null) { + resolveIntents(contract.getCallback().getRequiredIntents(), resolver); + resolvePolicySets(contract.getCallback().getPolicySets(), resolver); + resolvePolicySets(contract.getCallback().getApplicablePolicySets(), resolver); + //inherit the contract's policy intents and policysets + addInheritedIntents(contract.getRequiredIntents(), contract.getCallback().getRequiredIntents()); + addInheritedPolicySets(contract.getPolicySets(), contract.getCallback().getPolicySets()); + addInheritedPolicySets(contract.getApplicablePolicySets(), contract.getCallback().getApplicablePolicySets()); + + for (int i = 0, n = contract.getCallback().getBindings().size(); i < n; i++) { + Binding binding = contract.getCallback().getBindings().get(i); + extensionProcessor.resolve(binding, resolver); + + if (binding instanceof IntentAttachPoint) { + IntentAttachPoint policiedBinding = (IntentAttachPoint)binding; + + if ( policiedBinding.getType().isUnresolved() ) { + IntentAttachPointType resolved = + resolver.resolveModel(IntentAttachPointType.class, + policiedBinding.getType()); + policiedBinding.setType(resolved); + } + + resolveIntents(policiedBinding.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(policiedBinding, policiedBinding.getType()); + } + + if (binding instanceof PolicySetAttachPoint) { + PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)binding; + resolvePolicySets(policiedBinding.getPolicySets(), resolver); + //validate if attached policysets apply to the binding + resolvePolicySets(policiedBinding.getApplicablePolicySets(), resolver); + //inherit the applicable policysets from parent contract as whatever applies to that + //applies to the binding as well + addInheritedPolicySets(contract.getApplicablePolicySets(), policiedBinding.getApplicablePolicySets()); + PolicyValidationUtils.validatePolicySets(policiedBinding); + } + + if (binding instanceof OperationsConfigurator) { + OperationsConfigurator opConfigurator = (OperationsConfigurator)binding; + for (ConfiguredOperation confOp : opConfigurator.getConfiguredOperations()) { + resolveIntents(confOp.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(confOp, ((PolicySetAttachPoint)binding).getType()); + + resolvePolicySets(confOp.getPolicySets(), resolver); + resolvePolicySets(confOp.getApplicablePolicySets(), resolver); + //inherit the applicable policysets from parent binding as whatever applies to that + //applies to the binding as well + addInheritedPolicySets(((PolicySetAttachPoint)binding).getApplicablePolicySets(), + confOp.getApplicablePolicySets()); + PolicyValidationUtils.validatePolicySets(confOp, ((PolicySetAttachPoint)binding).getType()); + } + } + } + } + } catch ( PolicyValidationException e ) { + throw new ContributionResolveException("PolicyValidation exceptions when processing service/reference '" + + contract.getName() + "' in '" + parentName + "'"); + } + } + } + + /** + * Resolve interface and callback interface on a list of abstract contracts. + * @param contracts the list of contracts + * @param resolver the resolver to use to resolve models + */ + protected void resolveAbstractContracts(List contracts, ModelResolver resolver) + throws ContributionResolveException { + for (AbstractContract contract : contracts) { + + // Resolve the interface contract + InterfaceContract interfaceContract = contract.getInterfaceContract(); + if (interfaceContract != null) { + extensionProcessor.resolve(interfaceContract, resolver); + } + } + } + + /** + * Returns a constrainingType attribute. + * @param componentType + * @return + */ + protected XAttr writeConstrainingType(ComponentType componentType) { + ConstrainingType constrainingType = componentType.getConstrainingType(); + if (constrainingType != null) + return new XAttr(Constants.CONSTRAINING_TYPE, constrainingType.getName()); + else + return null; + } + + /** + * Read a property value into a DOM document. + * @param element + * @param type + * @param reader + * @return + * @throws XMLStreamException + * @throws ContributionReadException + * @throws ParserConfigurationException + */ + protected Document readPropertyValue(QName element, QName type, XMLStreamReader reader) throws XMLStreamException, + ContributionReadException { + + Document document; + try { + if (documentBuilderFactory == null) { + documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + } + document = documentBuilderFactory.newDocumentBuilder().newDocument(); + } catch (ParserConfigurationException e) { + throw new ContributionReadException(e); + } + + // root element has no namespace and local name "value" + Element root = document.createElementNS(null, "value"); + if (type != null) { + org.w3c.dom.Attr xsi = document.createAttributeNS(XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi"); + xsi.setValue(W3C_XML_SCHEMA_INSTANCE_NS_URI); + root.setAttributeNodeNS(xsi); + + String prefix = type.getPrefix(); + if (prefix == null || prefix.length() == 0) { + prefix = "ns"; + } + + declareNamespace(root, prefix, type.getNamespaceURI()); + + org.w3c.dom.Attr xsiType = document.createAttributeNS(W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type"); + xsiType.setValue(prefix + ":" + type.getLocalPart()); + root.setAttributeNodeNS(xsiType); + } + document.appendChild(root); + + loadElement(reader, root); + return document; + } + + /** + * Create a DOM element + * @param document + * @param name + * @return + */ + private Element createElement(Document document, QName name) { + String prefix = name.getPrefix(); + String qname = + (prefix != null && prefix.length() > 0) ? prefix + ":" + name.getLocalPart() : name.getLocalPart(); + return document.createElementNS(name.getNamespaceURI(), qname); + } + + /** + * Declare a namespace. + * @param element + * @param prefix + * @param ns + */ + private void declareNamespace(Element element, String prefix, String ns) { + if (ns == null) { + ns = ""; + } + if (prefix == null) { + prefix = ""; + } + String qname = null; + if ("".equals(prefix)) { + qname = "xmlns"; + } else { + qname = "xmlns:" + prefix; + } + Node node = element; + boolean declared = false; + while (node != null && node.getNodeType() == Node.ELEMENT_NODE) { + NamedNodeMap attrs = node.getAttributes(); + if (attrs == null) { + break; + } + Node attr = attrs.getNamedItem(qname); + if (attr != null) { + declared = ns.equals(attr.getNodeValue()); + break; + } + node = node.getParentNode(); + } + if (!declared) { + org.w3c.dom.Attr attr = element.getOwnerDocument().createAttributeNS(XMLNS_ATTRIBUTE_NS_URI, qname); + attr.setValue(ns); + element.setAttributeNodeNS(attr); + } + } + + /** + * Load a property value specification from an StAX stream into a DOM + * Document. Only elements, text and attributes are processed; all comments + * and other whitespace are ignored. + * + * @param reader the stream to read from + * @param root the DOM node to load + * @throws javax.xml.stream.XMLStreamException + */ + private void loadElement(XMLStreamReader reader, Element root) throws XMLStreamException { + Document document = root.getOwnerDocument(); + Node current = root; + while (true) { + switch (reader.next()) { + case XMLStreamConstants.START_ELEMENT: + QName name = reader.getName(); + Element child = createElement(document, name); + + // push the new element and make it the current one + current.appendChild(child); + current = child; + + int count = reader.getNamespaceCount(); + for (int i = 0; i < count; i++) { + String prefix = reader.getNamespacePrefix(i); + String ns = reader.getNamespaceURI(i); + declareNamespace(child, prefix, ns); + } + + if (!"".equals(name.getNamespaceURI())) { + declareNamespace(child, name.getPrefix(), name.getNamespaceURI()); + } + + // add the attributes for this element + count = reader.getAttributeCount(); + for (int i = 0; i < count; i++) { + String ns = reader.getAttributeNamespace(i); + String prefix = reader.getAttributePrefix(i); + String qname = reader.getAttributeLocalName(i); + String value = reader.getAttributeValue(i); + if (prefix != null && prefix.length() != 0) { + qname = prefix + ":" + qname; + } + child.setAttributeNS(ns, qname, value); + if (ns != null) { + declareNamespace(child, prefix, ns); + } + } + + break; + case XMLStreamConstants.CDATA: + current.appendChild(document.createCDATASection(reader.getText())); + break; + case XMLStreamConstants.CHARACTERS: + current.appendChild(document.createTextNode(reader.getText())); + break; + case XMLStreamConstants.END_ELEMENT: + // if we are back at the root then we are done + if (current == root) { + return; + } + + // pop the element off the stack + current = current.getParentNode(); + } + } + } + + /** + * Resolve policy intents attached to a specific SCA Artifact + * @param policyIntents list of policy intents + * @param resolver + */ + protected void resolveIntents(List policyIntents, ModelResolver resolver) { + List requiredIntents = new ArrayList(); + Intent resolvedIntent = null; + for (Intent intent : policyIntents) { + resolvedIntent = resolver.resolveModel(Intent.class, intent); + requiredIntents.add(resolvedIntent); + } + policyIntents.clear(); + policyIntents.addAll(requiredIntents); + } + + /** + * Resolve policy sets attached to a specific SCA Construct + * @param policySets list of attached policy sets + * @param resolver + */ + protected void resolvePolicySets(List policySets, ModelResolver resolver) { + List resolvedPolicySets = new ArrayList(); + PolicySet resolvedPolicySet = null; + for (PolicySet policySet : policySets) { + resolvedPolicySet = resolver.resolveModel(PolicySet.class, policySet); + resolvedPolicySets.add(resolvedPolicySet); + } + policySets.clear(); + policySets.addAll(resolvedPolicySets); + } + + /** + * Write the value of a property + * @param document + * @param element + * @param type + * @param writer + * @throws XMLStreamException + */ + protected void writePropertyValue(Object propertyValue, QName element, QName type, XMLStreamWriter writer) + throws XMLStreamException { + + if (propertyValue instanceof Document) { + Document document = (Document)propertyValue; + NodeList nodeList = document.getDocumentElement().getChildNodes(); + + for (int item = 0; item < nodeList.getLength(); ++item) { + Node node = nodeList.item(item); + int nodeType = node.getNodeType(); + if (nodeType == Node.ELEMENT_NODE) { + XMLStreamReader reader = + XMLInputFactory.newInstance().createXMLStreamReader(new DOMSource(node)); + + while (reader.hasNext()) { + switch (reader.next()) { + case XMLStreamConstants.START_ELEMENT: + QName name = reader.getName(); + writer.writeStartElement(name.getPrefix(), name.getLocalPart(), name.getNamespaceURI()); + + int namespaces = reader.getNamespaceCount(); + for (int i = 0; i < namespaces; i++) { + String prefix = reader.getNamespacePrefix(i); + String ns = reader.getNamespaceURI(i); + writer.writeNamespace(prefix, ns); + } + + if (!"".equals(name.getNamespaceURI())) { + writer.writeNamespace(name.getPrefix(), name.getNamespaceURI()); + } + + // add the attributes for this element + namespaces = reader.getAttributeCount(); + for (int i = 0; i < namespaces; i++) { + String ns = reader.getAttributeNamespace(i); + String prefix = reader.getAttributePrefix(i); + String qname = reader.getAttributeLocalName(i); + String value = reader.getAttributeValue(i); + + writer.writeAttribute(prefix, ns, qname, value); + } + + break; + case XMLStreamConstants.CDATA: + writer.writeCData(reader.getText()); + break; + case XMLStreamConstants.CHARACTERS: + writer.writeCharacters(reader.getText()); + break; + case XMLStreamConstants.END_ELEMENT: + writer.writeEndElement(); + break; + } + } + } else { + writer.writeCharacters(node.getTextContent()); + } + } + } + } + + protected void addInheritedIntents(List sourceList, List targetList) { + if (sourceList != null) { + targetList.addAll(sourceList); + } + } + + protected void addInheritedPolicySets(List sourceList, List targetList) { + if (sourceList != null) { + targetList.addAll(sourceList); + } + } + + + /*protected void validatePolicySets(PolicySetAttachPoint policySetAttachPoint) + throws ContributionResolveException { + validatePolicySets(policySetAttachPoint, policySetAttachPoint.getApplicablePolicySets()); + } + + + protected void validatePolicySets(PolicySetAttachPoint policySetAttachPoint, + List applicablePolicySets) throws ContributionResolveException { + //Since the applicablePolicySets in a policySetAttachPoint will already have the + //list of policysets that might ever be applicable to this attachPoint, just check + //if the defined policysets feature in the list of applicable policysets + IntentAttachPointType attachPointType = policySetAttachPoint.getType(); + for ( PolicySet definedPolicySet : policySetAttachPoint.getPolicySets() ) { + if ( !definedPolicySet.isUnresolved() ) { + if ( !applicablePolicySets.contains(definedPolicySet)) { + throw new ContributionResolveException("Policy Set '" + definedPolicySet.getName() + + "' does not apply to binding type " + + attachPointType.getName()); + } + } else { + throw new ContributionResolveException("Policy Set '" + definedPolicySet.getName() + + "' is not defined in this domain "); + + + } + } + }*/ +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeDocumentProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeDocumentProcessor.java new file mode 100644 index 0000000000..2950ef5a04 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeDocumentProcessor.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; + +/** + * A componentType processor. + * + * @version $Rev: 635373 $ $Date: 2008-03-09 14:51:51 -0700 (Sun, 09 Mar 2008) $ + */ +public class ComponentTypeDocumentProcessor extends BaseAssemblyProcessor implements URLArtifactProcessor { + private XMLInputFactory inputFactory; + + /** + * Constructs a new componentType processor. + * @param factory + * @param policyFactory + * @param registry + */ + public ComponentTypeDocumentProcessor(StAXArtifactProcessor staxProcessor, XMLInputFactory inputFactory) { + super(null, null, staxProcessor); + this.inputFactory = inputFactory; + } + + public ComponentType read(URL contributionURL, URI uri, URL url) throws ContributionReadException { + InputStream urlStream = null; + try { + + // Create a stream reader + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + urlStream = connection.getInputStream(); + XMLStreamReader reader = inputFactory.createXMLStreamReader(url.toString(), urlStream); + reader.nextTag(); + + // Reader the componentType model + ComponentType componentType = (ComponentType)extensionProcessor.read(reader); + if (componentType != null) { + componentType.setURI(uri.toString()); + } + + // For debugging purposes, write it back to XML +// if (componentType != null) { +// try { +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +// outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); +// extensionProcessor.write(componentType, outputFactory.createXMLStreamWriter(bos)); +// Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(bos.toByteArray())); +// OutputFormat format = new OutputFormat(); +// format.setIndenting(true); +// format.setIndent(2); +// XMLSerializer serializer = new XMLSerializer(System.out, format); +// serializer.serialize(document); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + + return componentType; + + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } catch (IOException e) { + throw new ContributionReadException(e); + } finally { + try { + if (urlStream != null) { + urlStream.close(); + urlStream = null; + } + } catch (IOException ioe) { + //ignore + } + } + } + + public void resolve(ComponentType componentType, ModelResolver resolver) throws ContributionResolveException { + extensionProcessor.resolve(componentType, resolver); + } + + public String getArtifactType() { + return ".componentType"; + } + + public Class getModelType() { + return ComponentType.class; + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeModelResolver.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeModelResolver.java new file mode 100644 index 0000000000..241e18badf --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeModelResolver.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.assembly.xml; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.java.JavaImport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * A Model Resolver for ComponentType models. + * + * @version $Rev: 631056 $ $Date: 2008-02-25 17:28:13 -0800 (Mon, 25 Feb 2008) $ + */ +public class ComponentTypeModelResolver implements ModelResolver { + private Contribution contribution; + private Map map = new HashMap(); + + public ComponentTypeModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) { + this.contribution = contribution; + } + + public void addModel(Object resolved) { + ComponentType componentType = (ComponentType)resolved; + map.put(componentType.getURI(), componentType); + } + + public Object removeModel(Object resolved) { + return map.remove(((ComponentType)resolved).getURI()); + } + + public T resolveModel(Class modelClass, T unresolved) { + + //get componentType artifact URI + String uri = ((ComponentType)unresolved).getURI(); + if (uri == null) { + return (T)unresolved; + } + + //lookup the componentType + ComponentType resolved = (ComponentType) map.get(uri); + if (resolved != null) { + return modelClass.cast(resolved); + } + + //If not found, delegate the resolution to the imports (in this case based on the java imports) + //compute the package name from the componentType URI + if (unresolved instanceof ComponentType) { + //FIXME The core assembly model now depends on java imports to + // resolve componentTypes of all kinds, this is not right at all!!! + int s = uri.lastIndexOf('/'); + if (s != -1) { + String packageName = uri.substring(0, uri.lastIndexOf("/")); + for (Import import_ : this.contribution.getImports()) { + if (import_ instanceof JavaImport) { + JavaImport javaImport = (JavaImport)import_; + //check the import location against the computed package name from the componentType URI + if (javaImport.getPackage().equals(packageName)) { + // Delegate the resolution to the import resolver + resolved = javaImport.getModelResolver().resolveModel(ComponentType.class, (ComponentType)unresolved); + if (!resolved.isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + } + } + } + + return (T)unresolved; + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeProcessor.java new file mode 100644 index 0000000000..760e202ed2 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ComponentTypeProcessor.java @@ -0,0 +1,355 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +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.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Callback; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.w3c.dom.Document; + +/** + * A componentType processor. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public class ComponentTypeProcessor extends BaseAssemblyProcessor implements StAXArtifactProcessor { + + /** + * Constructs a new componentType processor. + * @param factory + * @param policyFactory + * @param registry + */ + public ComponentTypeProcessor(AssemblyFactory factory, PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + super(factory, policyFactory, extensionProcessor); + } + + public ComponentType read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + ComponentType componentType = null; + Service service = null; + Reference reference = null; + Contract contract = null; + Property property = null; + Callback callback = null; + QName name = null; + + // Read the componentType document + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + name = reader.getName(); + + if (Constants.COMPONENT_TYPE_QNAME.equals(name)) { + + // Read a + componentType = assemblyFactory.createComponentType(); + componentType.setConstrainingType(readConstrainingType(reader)); + + } else if (Constants.SERVICE_QNAME.equals(name)) { + + // Read a + service = assemblyFactory.createService(); + contract = service; + service.setName(getString(reader, Constants.NAME)); + componentType.getServices().add(service); + policyProcessor.readPolicies(service, reader); + + } else if (Constants.REFERENCE_QNAME.equals(name)) { + + // Read a + reference = assemblyFactory.createReference(); + contract = reference; + reference.setName(getString(reader, Constants.NAME)); + reference.setWiredByImpl(getBoolean(reader, Constants.WIRED_BY_IMPL)); + readMultiplicity(reference, reader); + readTargets(reference, reader); + componentType.getReferences().add(reference); + policyProcessor.readPolicies(reference, reader); + + } else if (Constants.PROPERTY_QNAME.equals(name)) { + + // Read a + property = assemblyFactory.createProperty(); + readAbstractProperty(property, reader); + policyProcessor.readPolicies(property, reader); + + // Read the property value + Document value = readPropertyValue(property.getXSDElement(), property.getXSDType(), reader); + property.setValue(value); + + componentType.getProperties().add(property); + + } else if (Constants.IMPLEMENTATION_QNAME.equals(name)) { + + // Read an element + policyProcessor.readPolicies(componentType, reader); + + } else if (Constants.CALLBACK_QNAME.equals(name)) { + + // Read a + callback = assemblyFactory.createCallback(); + contract.setCallback(callback); + policyProcessor.readPolicies(callback, reader); + + } else if (OPERATION.equals(name)) { + + // Read an + Operation operation = new OperationImpl(); + operation.setName(getString(reader, NAME)); + operation.setUnresolved(true); + if (callback != null) { + policyProcessor.readPolicies(callback, operation, reader); + } else { + policyProcessor.readPolicies(contract, operation, reader); + } + } else { + + // Read an extension element + Object extension = extensionProcessor.read(reader); + if (extension != null) { + if (extension instanceof InterfaceContract) { + + // and + contract.setInterfaceContract((InterfaceContract)extension); + + } else if (extension instanceof Binding) { + + // and + if (callback != null) { + callback.getBindings().add((Binding)extension); + } else { + contract.getBindings().add((Binding)extension); + } + } else { + + // Add the extension element to the current element + if (callback != null) { + callback.getExtensions().add(extension); + } else if (contract != null) { + contract.getExtensions().add(extension); + } else if (property != null) { + property.getExtensions().add(extension); + } else { + if (componentType instanceof Extensible) { + ((Extensible)componentType).getExtensions().add(extension); + } + } + } + } + } + break; + + case END_ELEMENT: + name = reader.getName(); + + // Clear current state when reading reaching end element + if (SERVICE_QNAME.equals(name)) { + service = null; + contract = null; + } else if (REFERENCE_QNAME.equals(name)) { + reference = null; + contract = null; + } else if (PROPERTY_QNAME.equals(name)) { + property = null; + } else if (CALLBACK_QNAME.equals(name)) { + callback = null; + } + break; + } + + // Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + return componentType; + } + + public void write(ComponentType componentType, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + // Write element + writeStartDocument(writer, COMPONENT_TYPE, + writeConstrainingType(componentType)); + + // Write elements + for (Service service : componentType.getServices()) { + writeStart(writer, SERVICE, new XAttr(NAME, service.getName()), + policyProcessor.writePolicies(service)); + + if (service.getInterfaceContract() != null) { + extensionProcessor.write(service.getInterfaceContract(), writer); + } + + for (Binding binding: service.getBindings()) { + extensionProcessor.write(binding, writer); + } + + if (service.getCallback() != null) { + Callback callback = service.getCallback(); + writeStart(writer, CALLBACK, policyProcessor.writePolicies(callback)); + + for (Binding binding: callback.getBindings()) { + extensionProcessor.write(binding, writer); + } + for (Object extension: callback.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + for (Object extension: service.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (Reference reference : componentType.getReferences()) { + + writeStart(writer, REFERENCE, + new XAttr(NAME, reference.getName()), + writeTargets(reference), + policyProcessor.writePolicies(reference)); + + extensionProcessor.write(reference.getInterfaceContract(), writer); + + for (Binding binding: reference.getBindings()) { + extensionProcessor.write(binding, writer); + } + + if (reference.getCallback() != null) { + Callback callback = reference.getCallback(); + writeStart(writer, CALLBACK, + policyProcessor.writePolicies(callback)); + + for (Binding binding: callback.getBindings()) { + extensionProcessor.write(binding, writer); + } + for (Object extension: callback.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + for (Object extension: reference.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (Property property : componentType.getProperties()) { + writeStart(writer, + PROPERTY, + new XAttr(NAME, property.getName()), + new XAttr(MUST_SUPPLY, property.isMustSupply()), + new XAttr(MANY, property.isMany()), + new XAttr(TYPE, property.getXSDType()), + new XAttr(ELEMENT, property.getXSDElement()), + policyProcessor.writePolicies(property)); + + // Write property value + writePropertyValue(property.getValue(), property.getXSDElement(), property.getXSDType(), writer); + + // Write extensions + for (Object extension : property.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write extension elements + if (componentType instanceof Extensible) { + for (Object extension: ((Extensible)componentType).getExtensions()) { + extensionProcessor.write(extension, writer); + } + } + + // Write elements if the componentType has + // any intents or policySets + boolean writeImplementation = false; + if (componentType instanceof IntentAttachPoint) { + if (!((IntentAttachPoint)componentType).getRequiredIntents().isEmpty()) { + writeImplementation = true; + } + } + if (componentType instanceof PolicySetAttachPoint) { + if (!((PolicySetAttachPoint)componentType).getPolicySets().isEmpty()) { + writeImplementation = true; + } + } + if (writeImplementation) { + writeStart(writer, IMPLEMENTATION, + policyProcessor.writePolicies(componentType)); + } + + writeEndDocument(writer); + } + + public void resolve(ComponentType componentType, ModelResolver resolver) throws ContributionResolveException { + + // Resolve component type services and references + resolveContracts(componentType.getServices(), resolver); + resolveContracts(componentType.getReferences(), resolver); + if ( componentType instanceof PolicySetAttachPoint ) { + resolveIntents(((PolicySetAttachPoint)componentType).getRequiredIntents(), resolver); + resolvePolicySets(((PolicySetAttachPoint)componentType).getPolicySets(), resolver); + } + } + + public QName getArtifactType() { + return COMPONENT_TYPE_QNAME; + } + + public Class getModelType() { + return ComponentType.class; + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeDocumentProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeDocumentProcessor.java new file mode 100644 index 0000000000..2f3f66e14f --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeDocumentProcessor.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.Collection; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.util.PolicyComputationUtils; + +/** + * A composite processor. + * + * @version $Rev: 643489 $ $Date: 2008-04-01 10:06:42 -0800 (Tue, 01 Apr 2008) $ + */ +public class CompositeDocumentProcessor extends BaseAssemblyProcessor implements URLArtifactProcessor { + private XMLInputFactory inputFactory; + private List scaDefnSink; + private Collection domainPolicySets = null; + private int scaDefnsCount = 0; + + /** + * Construct a new composite processor + * @param assemblyFactory + * @param policyFactory + * @param staxProcessor + */ + public CompositeDocumentProcessor(StAXArtifactProcessor staxProcessor, XMLInputFactory inputFactory, List scaDefnsSink) { + super(null, null, staxProcessor); + this.inputFactory = inputFactory; + this.scaDefnSink = scaDefnsSink; + } + + public Composite read(URL contributionURL, URI uri, URL url) throws ContributionReadException { + InputStream scdlStream = null; + try { + if (scaDefnSink != null ) { + fillDomainPolicySets(scaDefnSink); + } + + + byte[] transformedArtifactContent = null; + try { + if ( domainPolicySets != null ) { + transformedArtifactContent = + PolicyComputationUtils.addApplicablePolicySets(url, domainPolicySets); + scdlStream = new ByteArrayInputStream(transformedArtifactContent); + } else { + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + scdlStream = connection.getInputStream(); + } + } catch ( Exception e ) { + throw new ContributionReadException(e); + } + + XMLStreamReader reader = inputFactory.createXMLStreamReader(scdlStream); + + reader.nextTag(); + + // Read the composite model + Composite composite = (Composite)extensionProcessor.read(reader); + if (composite != null) { + composite.setURI(uri.toString()); + } + + // For debugging purposes, write it back to XML +// if (composite != null) { +// try { +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +// outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); +// extensionProcessor.write(composite, outputFactory.createXMLStreamWriter(bos)); +// Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(bos.toByteArray())); +// OutputFormat format = new OutputFormat(); +// format.setIndenting(true); +// format.setIndent(2); +// XMLSerializer serializer = new XMLSerializer(System.out, format); +// serializer.serialize(document); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + + return composite; + + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } finally { + try { + if (scdlStream != null) { + scdlStream.close(); + scdlStream = null; + } + } catch (IOException ioe) { + //ignore + } + } + } + + public void resolve(Composite composite, ModelResolver resolver) throws ContributionResolveException { + extensionProcessor.resolve(composite, resolver); + } + + public String getArtifactType() { + return ".composite"; + } + + public Class getModelType() { + return Composite.class; + } + + private void fillDomainPolicySets(List scaDefnsSink) { + Map domainPolicySetMap = null; + if ( scaDefnsSink.size() > scaDefnsCount ) { + //if ( !scaDefnsSink.isEmpty() ) { + domainPolicySetMap = new Hashtable(); + + if ( domainPolicySets != null ) { + for ( PolicySet policySet : domainPolicySets ) { + domainPolicySetMap.put(policySet.getName(), policySet); + } + } + + for ( Object object : scaDefnsSink ) { + if ( object instanceof SCADefinitions ) { + for ( PolicySet policySet : ((SCADefinitions)object).getPolicySets() ) { + domainPolicySetMap.put( policySet.getName(), policySet); + } + } + } + domainPolicySets = domainPolicySetMap.values(); + //scaDefnsSink.clear(); + scaDefnsCount = scaDefnsSink.size(); + } + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeModelResolver.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeModelResolver.java new file mode 100644 index 0000000000..e939fe2c05 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeModelResolver.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * A Model Resolver for Composite models. + * + * @version $Rev: 572482 $ $Date: 2007-09-03 18:28:31 -0700 (Mon, 03 Sep 2007) $ + */ +public class CompositeModelResolver implements ModelResolver { + + private Contribution contribution; + private Map map = new HashMap(); + + public CompositeModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) { + this.contribution = contribution; + } + + public void addModel(Object resolved) { + Composite composite = (Composite)resolved; + map.put(composite.getName(), composite); + } + + public Object removeModel(Object resolved) { + return map.remove(((Composite)resolved).getName()); + } + + public T resolveModel(Class modelClass, T unresolved) { + + // Lookup a definition for the given namespace + QName qname = ((Composite)unresolved).getName(); + Composite resolved = (Composite) map.get(qname); + if (resolved != null) { + return modelClass.cast(resolved); + } + + // No definition found, delegate the resolution to the imports + for (Import import_ : this.contribution.getImports()) { + if (import_ instanceof NamespaceImport) { + NamespaceImport namespaceImport = (NamespaceImport)import_; + if (namespaceImport.getNamespace().equals(qname.getNamespaceURI())) { + + // Delegate the resolution to the import resolver + resolved = namespaceImport.getModelResolver().resolveModel(Composite.class, (Composite)unresolved); + if (!resolved.isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + } + return (T)unresolved; + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java new file mode 100644 index 0000000000..c74c5bfb5b --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/CompositeProcessor.java @@ -0,0 +1,989 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Callback; +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.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.Wire; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.util.PolicyValidationException; +import org.apache.tuscany.sca.policy.util.PolicyValidationUtils; +import org.w3c.dom.Document; + +/** + * A composite processor. + * + * @version $Rev: 639226 $ $Date: 2008-03-20 02:45:37 -0700 (Thu, 20 Mar 2008) $ + */ +public class CompositeProcessor extends BaseAssemblyProcessor implements StAXArtifactProcessor { + // FIXME: to be refactored + // private XPathFactory xPathFactory = XPathFactory.newInstance(); + + /** + * Construct a new composite processor + * + * @param contributionFactory + * @param assemblyFactory + * @param policyFactory + * @param extensionProcessor + */ + public CompositeProcessor(ContributionFactory contributionFactory, + AssemblyFactory factory, + PolicyFactory policyFactory, + InterfaceContractMapper interfaceContractMapper, + StAXArtifactProcessor extensionProcessor) { + super(contributionFactory, factory, policyFactory, extensionProcessor); + + } + + /** + * Construct a new composite processor + * + * @param contributionFactory + * @param assemblyFactory + * @param policyFactory + * @param extensionProcessor + */ + public CompositeProcessor(ContributionFactory contributionFactory, + AssemblyFactory factory, + PolicyFactory policyFactory, + StAXArtifactProcessor extensionProcessor) { + super(contributionFactory, factory, policyFactory, extensionProcessor); + } + + public Composite read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + Composite composite = null; + Composite include = null; + Component component = null; + Property property = null; + ComponentService componentService = null; + ComponentReference componentReference = null; + ComponentProperty componentProperty = null; + CompositeService compositeService = null; + CompositeReference compositeReference = null; + Contract contract = null; + Wire wire = null; + Callback callback = null; + QName name = null; + + // Read the composite document + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: + name = reader.getName(); + + if (COMPOSITE_QNAME.equals(name)) { + + // Read a + composite = assemblyFactory.createComposite(); + composite.setName(new QName(getString(reader, TARGET_NAMESPACE), getString(reader, NAME))); + if(isSet(reader, AUTOWIRE)) { + composite.setAutowire(getBoolean(reader, AUTOWIRE)); + } + composite.setLocal(getBoolean(reader, LOCAL)); + composite.setConstrainingType(readConstrainingType(reader)); + policyProcessor.readPolicies(composite, reader); + + } else if (INCLUDE_QNAME.equals(name)) { + + // Read an + include = assemblyFactory.createComposite(); + include.setName(getQName(reader, NAME)); + include.setURI(getString(reader, URI)); + include.setUnresolved(true); + composite.getIncludes().add(include); + + } else if (SERVICE_QNAME.equals(name)) { + if (component != null) { + + // Read a + componentService = assemblyFactory.createComponentService(); + contract = componentService; + componentService.setName(getString(reader, NAME)); + component.getServices().add(componentService); + policyProcessor.readPolicies(contract, reader); + } else { + + // Read a + compositeService = assemblyFactory.createCompositeService(); + contract = compositeService; + compositeService.setName(getString(reader, NAME)); + + String promoted = getString(reader, PROMOTE); + String promotedComponentName; + String promotedServiceName; + int s = promoted.indexOf('/'); + if (s == -1) { + promotedComponentName = promoted; + promotedServiceName = null; + } else { + promotedComponentName = promoted.substring(0, s); + promotedServiceName = promoted.substring(s + 1); + } + + Component promotedComponent = assemblyFactory.createComponent(); + promotedComponent.setUnresolved(true); + promotedComponent.setName(promotedComponentName); + compositeService.setPromotedComponent(promotedComponent); + + ComponentService promotedService = assemblyFactory.createComponentService(); + promotedService.setUnresolved(true); + promotedService.setName(promotedServiceName); + compositeService.setPromotedService(promotedService); + + composite.getServices().add(compositeService); + policyProcessor.readPolicies(contract, reader); + } + + } else if (REFERENCE_QNAME.equals(name)) { + if (component != null) { + // Read a + componentReference = assemblyFactory.createComponentReference(); + contract = componentReference; + componentReference.setName(getString(reader, NAME)); + readMultiplicity(componentReference, reader); + if (isSet(reader, AUTOWIRE)) { + componentReference.setAutowire(getBoolean(reader, AUTOWIRE)); + } + readTargets(componentReference, reader); + componentReference.setWiredByImpl(getBoolean(reader, WIRED_BY_IMPL)); + component.getReferences().add(componentReference); + policyProcessor.readPolicies(contract, reader); + } else { + // Read a + compositeReference = assemblyFactory.createCompositeReference(); + contract = compositeReference; + compositeReference.setName(getString(reader, NAME)); + readMultiplicity(compositeReference, reader); + readTargets(compositeReference, reader); + String promote = reader.getAttributeValue(null, Constants.PROMOTE); + if (promote != null) { + for (StringTokenizer tokens = new StringTokenizer(promote); tokens.hasMoreTokens();) { + ComponentReference promotedReference = + assemblyFactory.createComponentReference(); + promotedReference.setUnresolved(true); + promotedReference.setName(tokens.nextToken()); + compositeReference.getPromotedReferences().add(promotedReference); + } + } + compositeReference.setWiredByImpl(getBoolean(reader, WIRED_BY_IMPL)); + composite.getReferences().add(compositeReference); + policyProcessor.readPolicies(contract, reader); + } + + } else if (PROPERTY_QNAME.equals(name)) { + if (component != null) { + + // Read a + componentProperty = assemblyFactory.createComponentProperty(); + property = componentProperty; + String source = getString(reader, SOURCE); + if(source!=null) { + source = source.trim(); + } + componentProperty.setSource(source); + if (source != null) { + // $/... + if (source.charAt(0) == '$') { + int index = source.indexOf('/'); + if (index == -1) { + // Tolerating $prop + source = source + "/"; + index = source.length() - 1; + } + source = source.substring(index + 1); + if ("".equals(source)) { + source = "."; + } + } + + throw new IllegalArgumentException("not implemented in Android!"); + + /* XPath xpath = xPathFactory.newXPath(); + xpath.setNamespaceContext(reader.getNamespaceContext()); + try { + componentProperty.setSourceXPathExpression(xpath.compile(source)); + } catch (XPathExpressionException e) { + throw new ContributionReadException(e); + }*/ + } + componentProperty.setFile(getString(reader, FILE)); + policyProcessor.readPolicies(property, reader); + readAbstractProperty(componentProperty, reader); + + // Read the property value + Document value = readPropertyValue(property.getXSDElement(), property.getXSDType(), reader); + property.setValue(value); + + component.getProperties().add(componentProperty); + } else { + + // Read a + property = assemblyFactory.createProperty(); + policyProcessor.readPolicies(property, reader); + readAbstractProperty(property, reader); + + // Read the property value + Document value = readPropertyValue(property.getXSDElement(), property.getXSDType(), reader); + property.setValue(value); + + composite.getProperties().add(property); + } + + // TUSCANY-1949 + // If the property doesn't have a value, the END_ELEMENT event is read by the readPropertyValue + if (reader.getEventType() == END_ELEMENT && PROPERTY_QNAME.equals(reader.getName())) { + property = null; + componentProperty = null; + } + + } else if (COMPONENT_QNAME.equals(name)) { + + // Read a + component = assemblyFactory.createComponent(); + component.setName(getString(reader, NAME)); + if (isSet(reader, AUTOWIRE)) { + component.setAutowire(getBoolean(reader, AUTOWIRE)); + } + if (isSet(reader, URI)) { + component.setURI(getString(reader, URI)); + } + component.setConstrainingType(readConstrainingType(reader)); + composite.getComponents().add(component); + policyProcessor.readPolicies(component, reader); + + } else if (WIRE_QNAME.equals(name)) { + + // Read a + wire = assemblyFactory.createWire(); + ComponentReference source = assemblyFactory.createComponentReference(); + source.setUnresolved(true); + source.setName(getString(reader, SOURCE)); + wire.setSource(source); + + ComponentService target = assemblyFactory.createComponentService(); + target.setUnresolved(true); + target.setName(getString(reader, TARGET)); + wire.setTarget(target); + + composite.getWires().add(wire); + policyProcessor.readPolicies(wire, reader); + + } else if (CALLBACK_QNAME.equals(name)) { + + // Read a + callback = assemblyFactory.createCallback(); + contract.setCallback(callback); + policyProcessor.readPolicies(callback, reader); + + } else if (OPERATION_QNAME.equals(name)) { + + // Read an + ConfiguredOperation operation = assemblyFactory.createConfiguredOperation(); + operation.setName(getString(reader, NAME)); + operation.setUnresolved(true); + if (callback != null) { + policyProcessor.readPolicies(operation, reader); + } else { + policyProcessor.readPolicies(operation, reader); + } + + OperationsConfigurator opConfigurator = null; + if ( compositeService != null ) { + opConfigurator = compositeService; + } else if ( componentService != null ) { + opConfigurator = componentService; + } else if ( compositeReference != null ) { + opConfigurator = compositeReference; + } else if ( componentReference != null ) { + opConfigurator = componentReference; + } + + opConfigurator.getConfiguredOperations().add(operation); + } else if (IMPLEMENTATION_COMPOSITE_QNAME.equals(name)) { + + // Read an implementation.composite + Composite implementation = assemblyFactory.createComposite(); + implementation.setName(getQName(reader, NAME)); + implementation.setUnresolved(true); + component.setImplementation(implementation); + policyProcessor.readPolicies(implementation, reader); + } else { + + // Read an extension element + Object extension = extensionProcessor.read(reader); + if (extension != null) { + if (extension instanceof InterfaceContract) { + + // and + // + if (contract != null) { + contract.setInterfaceContract((InterfaceContract)extension); + } else { + if (name.getNamespaceURI().equals(SCA10_NS)) { + throw new ContributionReadException( + "Unexpected element found. It should appear inside a or element"); + } else { + composite.getExtensions().add(extension); + } + } + } else if (extension instanceof Binding) { + if ( extension instanceof PolicySetAttachPoint ) { + IntentAttachPointType bindingType = intentAttachPointTypeFactory.createBindingType(); + bindingType.setName(name); + bindingType.setUnresolved(true); + ((PolicySetAttachPoint)extension).setType(bindingType); + } + // and + // + if (callback != null) { + callback.getBindings().add((Binding)extension); + } else { + if (contract != null) { + contract.getBindings().add((Binding)extension); + } else { + if (name.getNamespaceURI().equals(SCA10_NS)) { + throw new ContributionReadException( + "Unexpected element found. It should appear inside a or element"); + } else { + composite.getExtensions().add(extension); + } + } + } + + } else if (extension instanceof Implementation) { + if ( extension instanceof PolicySetAttachPoint ) { + IntentAttachPointType implType = intentAttachPointTypeFactory.createImplementationType(); + implType.setName(name); + implType.setUnresolved(true); + ((PolicySetAttachPoint)extension).setType(implType); + } + // + if (component != null) { + component.setImplementation((Implementation)extension); + } else { + if (name.getNamespaceURI().equals(SCA10_NS)) { + throw new ContributionReadException( + "Unexpected element found. It should appear inside a element"); + } else { + composite.getExtensions().add(extension); + } + } + } else { + + // Add the extension element to the current + // element + if (callback != null) { + callback.getExtensions().add(extension); + } else if (contract != null) { + contract.getExtensions().add(extension); + } else if (property != null) { + property.getExtensions().add(extension); + } else if (component != null) { + component.getExtensions().add(extension); + } else { + composite.getExtensions().add(extension); + } + } + } + } + break; + + case XMLStreamConstants.CHARACTERS: + break; + + case END_ELEMENT: + name = reader.getName(); + + // Clear current state when reading reaching end element + if (SERVICE_QNAME.equals(name)) { + componentService = null; + compositeService = null; + contract = null; + } else if (INCLUDE_QNAME.equals(name)) { + include = null; + } else if (REFERENCE_QNAME.equals(name)) { + componentReference = null; + compositeReference = null; + contract = null; + } else if (PROPERTY_QNAME.equals(name)) { + componentProperty = null; + property = null; + } else if (COMPONENT_QNAME.equals(name)) { + component = null; + } else if (WIRE_QNAME.equals(name)) { + wire = null; + } else if (CALLBACK_QNAME.equals(name)) { + callback = null; + } + break; + } + + // Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + return composite; + } + + public void write(Composite composite, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + // Write element + writeStartDocument(writer, + COMPOSITE, + writeConstrainingType(composite), + new XAttr(TARGET_NAMESPACE, composite.getName().getNamespaceURI()), + new XAttr(NAME, composite.getName().getLocalPart()), + new XAttr(AUTOWIRE, composite.getAutowire()), + policyProcessor.writePolicies(composite)); + + // Write elements + for (Composite include : composite.getIncludes()) { + String uri = include.isUnresolved()? include.getURI() : null; + writeStart(writer, + INCLUDE, + new XAttr(NAME, include.getName()), + new XAttr(URI, uri)); + writeEnd(writer); + } + + // Write elements + for (Service service : composite.getServices()) { + CompositeService compositeService = (CompositeService)service; + Component promotedComponent = compositeService.getPromotedComponent(); + ComponentService promotedService = compositeService.getPromotedService(); + String promote; + if (promotedService != null) { + if (promotedService.getName() != null) { + promote = promotedComponent.getName() + '/' + promotedService.getService(); + } else { + promote = promotedComponent.getName(); + } + } else { + promote = null; + } + writeStart(writer, SERVICE, new XAttr(NAME, service.getName()), new XAttr(PROMOTE, promote), + policyProcessor.writePolicies(service)); + + // Write service interface + extensionProcessor.write(service.getInterfaceContract(), writer); + + // Write bindings + for (Binding binding : service.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write element + if (service.getCallback() != null) { + Callback callback = service.getCallback(); + writeStart(writer, CALLBACK, + policyProcessor.writePolicies(callback)); + + // Write callback bindings + for (Binding binding : callback.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write extensions + for (Object extension : callback.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write extensions + for (Object extension : service.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (Component component : composite.getComponents()) { + writeStart(writer, COMPONENT, new XAttr(NAME, component.getName()), + new XAttr(URI, component.getURI()), + new XAttr(AUTOWIRE, component.getAutowire()), + policyProcessor.writePolicies(component)); + + // Write the component implementation + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + writeStart(writer, IMPLEMENTATION_COMPOSITE, new XAttr(NAME, composite.getName())); + writeEnd(writer); + } else { + extensionProcessor.write(component.getImplementation(), writer); + } + + // Write elements + for (ComponentService service : component.getServices()) { + writeStart(writer, SERVICE, new XAttr(NAME, service.getName()), + policyProcessor.writePolicies(service)); + + // Write service interface + extensionProcessor.write(service.getInterfaceContract(), writer); + + // Write bindings + for (Binding binding : service.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write element + if (service.getCallback() != null) { + Callback callback = service.getCallback(); + writeStart(writer, CALLBACK, policyProcessor.writePolicies(callback)); + + // Write bindings + for (Binding binding : callback.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write extensions + for (Object extension : callback.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write extensions + for (Object extension : service.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (ComponentReference reference : component.getReferences()) { + writeStart(writer, REFERENCE, new XAttr(NAME, reference.getName()), + new XAttr(AUTOWIRE, reference.getAutowire()), + writeTargets(reference), + policyProcessor.writePolicies(reference)); + + // Write reference interface + extensionProcessor.write(reference.getInterfaceContract(), writer); + + // Write bindings + for (Binding binding : reference.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write callback + if (reference.getCallback() != null) { + Callback callback = reference.getCallback(); + writeStart(writer, CALLBACK, policyProcessor.writePolicies(callback)); + + // Write callback bindings + for (Binding binding : callback.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write extensions + for (Object extensions : callback.getExtensions()) { + extensionProcessor.write(extensions, writer); + } + + writeEnd(writer); + } + + // Write extensions + for (Object extensions : reference.getExtensions()) { + extensionProcessor.write(extensions, writer); + } + + writeEnd(writer); + } + + // Write elements + for (ComponentProperty property : component.getProperties()) { + writeStart(writer, + PROPERTY, + new XAttr(NAME, property.getName()), + new XAttr(MUST_SUPPLY, property.isMustSupply()), + new XAttr(MANY, property.isMany()), + new XAttr(TYPE, property.getXSDType()), + new XAttr(ELEMENT, property.getXSDElement()), + new XAttr(SOURCE, property.getSource()), + new XAttr(FILE, property.getFile()), + policyProcessor.writePolicies(property)); + + // Write property value + writePropertyValue(property.getValue(), property.getXSDElement(), property.getXSDType(), writer); + + // Write extensions + for (Object extension : property.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + writeEnd(writer); + } + + // Write elements + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + + // Write list of promoted references + List promote = new ArrayList(); + for (ComponentReference promoted: compositeReference.getPromotedReferences()) { + promote.add(promoted.getName()); + } + + // Write element + writeStart(writer, REFERENCE, new XAttr(NAME, reference.getName()), + new XAttr(PROMOTE, promote), + policyProcessor.writePolicies(reference)); + + // Write reference interface + extensionProcessor.write(reference.getInterfaceContract(), writer); + + // Write bindings + for (Binding binding : reference.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write element + if (reference.getCallback() != null) { + Callback callback = reference.getCallback(); + writeStart(writer, CALLBACK); + + // Write callback bindings + for (Binding binding : callback.getBindings()) { + extensionProcessor.write(binding, writer); + } + + // Write extensions + for (Object extension : callback.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write extensions + for (Object extension : reference.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (Property property : composite.getProperties()) { + writeStart(writer, + PROPERTY, + new XAttr(NAME, property.getName()), + new XAttr(MUST_SUPPLY, property.isMustSupply()), + new XAttr(MANY, property.isMany()), + new XAttr(TYPE, property.getXSDType()), + new XAttr(ELEMENT, property.getXSDElement()), + policyProcessor.writePolicies(property)); + + // Write property value + writePropertyValue(property.getValue(), property.getXSDElement(), property.getXSDType(), writer); + + // Write extensions + for (Object extension : property.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (Wire wire : composite.getWires()) { + writeStart(writer, WIRE, new XAttr(SOURCE, wire.getSource().getName()), new XAttr(TARGET, wire + .getTarget().getName())); + + // Write extensions + for (Object extension : wire.getExtensions()) { + extensionProcessor.write(extension, writer); + } + writeEnd(writer); + } + + for (Object extension : composite.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEndDocument(writer); + } + + public void resolve(Composite composite, ModelResolver resolver) throws ContributionResolveException { + + // Resolve constraining type + ConstrainingType constrainingType = composite.getConstrainingType(); + if (constrainingType != null) { + constrainingType = resolver.resolveModel(ConstrainingType.class, constrainingType); + composite.setConstrainingType(constrainingType); + } + + // Resolve includes in the composite + for (int i = 0, n = composite.getIncludes().size(); i < n; i++) { + Composite include = composite.getIncludes().get(i); + if (include != null) { + include = resolver.resolveModel(Composite.class, include); + composite.getIncludes().set(i, include); + } + } + + // Resolve extensions + for (Object extension : composite.getExtensions()) { + if (extension != null) { + extensionProcessor.resolve(extension, resolver); + } + } + + //resolve intents and policysets first as they are going to be copied over + //to child elements as and when the child elements are being resolved + List compositeIntents = null; + List compositePolicySets = null; + List compositeApplicablePolicySets = null; + if (composite instanceof PolicySetAttachPoint) { + resolveIntents(((PolicySetAttachPoint)composite).getRequiredIntents(), resolver); + resolvePolicySets(((PolicySetAttachPoint)composite).getPolicySets(), resolver); + resolvePolicySets(((PolicySetAttachPoint)composite).getApplicablePolicySets(), resolver); + compositeIntents = ((PolicySetAttachPoint)composite).getRequiredIntents(); + compositePolicySets = ((PolicySetAttachPoint)composite).getPolicySets(); + compositeApplicablePolicySets = ((PolicySetAttachPoint)composite).getApplicablePolicySets(); + } else { + compositeIntents = new ArrayList(); + compositePolicySets = new ArrayList(); + compositeApplicablePolicySets = new ArrayList(); + } + + //Resolve composite services and references + resolveContracts(composite, composite.getServices(), resolver); + resolveContracts(composite, composite.getReferences(), resolver); + + // Resolve component implementations, services and references + for (Component component : composite.getComponents()) { + constrainingType = component.getConstrainingType(); + if (constrainingType != null) { + constrainingType = resolver.resolveModel(ConstrainingType.class, constrainingType); + component.setConstrainingType(constrainingType); + } + + //resolve intents and policysets first as they are going to be copied over + //to child elements as and when the child elements are being resolved + resolveIntents(component.getRequiredIntents(), resolver); + resolvePolicySets(component.getPolicySets(), resolver); + resolvePolicySets(component.getApplicablePolicySets(), resolver); + + //inherit composite intents and policysets + addInheritedIntents(compositeIntents, component.getRequiredIntents()); + addInheritedPolicySets(compositePolicySets, component.getPolicySets()); + addInheritedPolicySets(compositeApplicablePolicySets, component.getApplicablePolicySets()); + + //resolve component services and references + resolveContracts(component, component.getServices(), resolver); + resolveContracts(component, component.getReferences(), resolver); + + for (ComponentProperty componentProperty : component.getProperties()) { + if (componentProperty.getFile() != null) { + Artifact artifact = contributionFactory.createArtifact(); + artifact.setURI(componentProperty.getFile()); + artifact = resolver.resolveModel(Artifact.class, artifact); + if (artifact.getLocation() != null) { + componentProperty.setFile(artifact.getLocation()); + } + } + } + + //resolve component implementation + Implementation implementation = component.getImplementation(); + if (implementation != null) { + try { + //resolve intents and policysets specified on this implementation + //before copying them over to the component. Before that, from the component + //copy over the applicablePolicySets alone as it might have to be + //used to validate the policysets specified on the implementation + + resolveImplIntentsAndPolicySets(implementation, + component.getApplicablePolicySets(), + resolver); + + copyPoliciesToComponent(component, implementation, resolver, true); + + //now resolve the implementation so that even if there is a shared instance + //for this that is resolved, the specified intents and policysets are safe in the + //component and not lost + implementation = resolveImplementation(implementation, resolver); + + //resolved implementation may contain intents and policysets specified at + //componentType (either in the componentType side file or in annotations if its a + //java implementation). This has to be consolidated in to the component. + copyPoliciesToComponent(component, implementation, resolver, false); + + component.setImplementation(implementation); + } catch ( PolicyValidationException e ) { + throw new ContributionResolveException("PolicyValidation exception when processing implementation of component '" + + component.getName() + "' due to " + e.getMessage(), e); + } + + } + } + } + + private void resolveImplIntentsAndPolicySets(Implementation implementation, + List inheritedApplicablePolicySets, + ModelResolver resolver) throws ContributionResolveException, + PolicyValidationException + { + if ( implementation instanceof PolicySetAttachPoint ) { + PolicySetAttachPoint policiedImpl = (PolicySetAttachPoint)implementation; + + policiedImpl.getApplicablePolicySets().addAll(inheritedApplicablePolicySets); + + resolveIntents(policiedImpl.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(policiedImpl, policiedImpl.getType()); + + resolvePolicySets(policiedImpl.getPolicySets(), resolver); + resolvePolicySets(policiedImpl.getApplicablePolicySets(), resolver); + + PolicyValidationUtils.validatePolicySets(policiedImpl); + + if ( implementation instanceof OperationsConfigurator ) { + for ( ConfiguredOperation implConfOp : ((OperationsConfigurator)implementation).getConfiguredOperations() ) { + resolveIntents(implConfOp.getRequiredIntents(), resolver); + PolicyValidationUtils.validateIntents(implConfOp, policiedImpl.getType()); + + resolvePolicySets(implConfOp.getPolicySets(), resolver); + resolvePolicySets(implConfOp.getApplicablePolicySets(), resolver); + //add the inherited applicablePolicysets + addInheritedPolicySets(policiedImpl.getApplicablePolicySets(), implConfOp.getApplicablePolicySets()); + + PolicyValidationUtils.validatePolicySets(implConfOp, policiedImpl.getType()); + + addInheritedIntents(((PolicySetAttachPoint)implementation).getRequiredIntents(), + implConfOp.getRequiredIntents()); + addInheritedPolicySets(((PolicySetAttachPoint)implementation).getPolicySets(), + implConfOp.getPolicySets()); + } + } + } + } + + private void copyPoliciesToComponent(Component component, + Implementation implementation, + ModelResolver resolver, + boolean clearImplSettings) throws ContributionResolveException { + if (implementation instanceof PolicySetAttachPoint) { + //add implementation policies into component... since implementation instance are + //reused and its likely that this implementation instance will not hold after its resolution + component.getRequiredIntents().addAll(((PolicySetAttachPoint)implementation).getRequiredIntents()); + component.getPolicySets().addAll(((PolicySetAttachPoint)implementation).getPolicySets()); + component.getApplicablePolicySets().addAll(((PolicySetAttachPoint)implementation).getApplicablePolicySets()); + + if ( implementation instanceof OperationsConfigurator ) { + boolean notFound; + List opsFromImplementation = new ArrayList(); + List implConfOperations = + new ArrayList(((OperationsConfigurator)implementation).getConfiguredOperations()); + for ( ConfiguredOperation implConfOp : implConfOperations ) { + notFound = true; + for ( ConfiguredOperation compConfOp : ((OperationsConfigurator)component).getConfiguredOperations() ) { + if ( implConfOp.getName().equals(compConfOp.getName()) ) { + notFound = false; + addInheritedIntents(implConfOp.getRequiredIntents(), compConfOp.getRequiredIntents()); + addInheritedPolicySets(implConfOp.getPolicySets(), compConfOp.getPolicySets()); + addInheritedPolicySets(implConfOp.getApplicablePolicySets(), compConfOp.getApplicablePolicySets()); + notFound = false; + } + } + + if ( notFound ) { + opsFromImplementation.add(implConfOp); + } + + if ( clearImplSettings ) { + ((OperationsConfigurator)implementation).getConfiguredOperations().remove(implConfOp); + } + } + ((OperationsConfigurator)component).getConfiguredOperations().addAll(opsFromImplementation); + } + + if ( clearImplSettings ) { + ((PolicySetAttachPoint)implementation).getRequiredIntents().clear(); + ((PolicySetAttachPoint)implementation).getPolicySets().clear(); + } + } + } + + + public QName getArtifactType() { + return COMPOSITE_QNAME; + } + + public Class getModelType() { + return Composite.class; + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConfiguredOperationProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConfiguredOperationProcessor.java new file mode 100644 index 0000000000..43e0242b7e --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConfiguredOperationProcessor.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +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.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Processor for dealing with 'operation' elements from composite definitions + */ +public class ConfiguredOperationProcessor implements StAXArtifactProcessor, Constants{ + + private AssemblyFactory assemblyFactory; + private PolicyAttachPointProcessor policyProcessor; + private PolicyFactory policyFactory; + + public ConfiguredOperationProcessor(ModelFactoryExtensionPoint modelFactories) { + this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + this.policyFactory = modelFactories.getFactory(PolicyFactory.class); + this.policyProcessor = new PolicyAttachPointProcessor(policyFactory); + } + + public ConfiguredOperation read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + ConfiguredOperation configuredOp = assemblyFactory.createConfiguredOperation(); + + //Read an + configuredOp.setName(reader.getAttributeValue(null, NAME)); + configuredOp.setContractName(reader.getAttributeValue(null, SERVICE)); + configuredOp.setUnresolved(true); + + // Read policies + policyProcessor.readPolicies(configuredOp, reader); + + //Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && OPERATION_QNAME.equals(reader.getName())) { + break; + } + } + + return configuredOp; + } + + public void write(ConfiguredOperation configuredOperation, XMLStreamWriter writer) + throws ContributionWriteException, XMLStreamException { + + // Write an + policyProcessor.writePolicyPrefixes(configuredOperation, writer); + writer.writeStartElement(Constants.SCA10_NS, OPERATION); + policyProcessor.writePolicyAttributes(configuredOperation, writer); + + writer.writeAttribute(NAME, configuredOperation.getName()); + if ( configuredOperation.getContractName() != null ) { + writer.writeAttribute(SERVICE, configuredOperation.getContractName()); + } + writer.writeEndElement(); + } + + public void resolve(ConfiguredOperation configuredOperation, ModelResolver resolver) + throws ContributionResolveException { + } + + public QName getArtifactType() { + return OPERATION_QNAME; + } + + public Class getModelType() { + return ConfiguredOperation.class; + } + +} + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/Constants.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/Constants.java new file mode 100644 index 0000000000..3f471838fc --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/Constants.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.assembly.xml; + +import javax.xml.namespace.QName; + +/** + * Constants used in SCA assembly XML files. + */ +public interface Constants { + String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0"; + String SCA10_TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.0"; + + String COMPONENT_TYPE = "componentType"; + QName COMPONENT_TYPE_QNAME = new QName(SCA10_NS, COMPONENT_TYPE); + + String SERVICE = "service"; + QName SERVICE_QNAME = new QName(SCA10_NS, SERVICE); + + String REFERENCE = "reference"; + QName REFERENCE_QNAME = new QName(SCA10_NS, REFERENCE); + + String PROPERTY = "property"; + QName PROPERTY_QNAME = new QName(SCA10_NS, PROPERTY); + + String CONSTRAINING_TYPE = "constrainingType"; + QName CONSTRAINING_TYPE_QNAME = new QName(SCA10_NS, CONSTRAINING_TYPE); + + String COMPOSITE = "composite"; + QName COMPOSITE_QNAME = new QName(SCA10_NS, COMPOSITE); + + String INCLUDE = "include"; + QName INCLUDE_QNAME = new QName(SCA10_NS, INCLUDE); + + String COMPONENT = "component"; + QName COMPONENT_QNAME = new QName(SCA10_NS, COMPONENT); + + String WIRE = "wire"; + QName WIRE_QNAME = new QName(SCA10_NS, WIRE); + + String OPERATION = "operation"; + QName OPERATION_QNAME = new QName(SCA10_NS, OPERATION); + + String CALLBACK = "callback"; + QName CALLBACK_QNAME = new QName(SCA10_NS, CALLBACK); + + String IMPLEMENTATION_COMPOSITE = "implementation.composite"; + QName IMPLEMENTATION_COMPOSITE_QNAME = new QName(SCA10_NS, IMPLEMENTATION_COMPOSITE); + + String IMPLEMENTATION = "implementation"; + QName IMPLEMENTATION_QNAME = new QName(SCA10_NS, IMPLEMENTATION); + + String BINDING_SCA = "binding.sca"; + QName BINDING_SCA_QNAME = new QName(Constants.SCA10_NS, BINDING_SCA); + + String NAME = "name"; + String TARGET_NAMESPACE = "targetNamespace"; + String LOCAL = "local"; + String AUTOWIRE = "autowire"; + String REQUIRES = "requires"; + String POLICY_SETS = "policySets"; + String APPLICABLE_POLICY_SETS = "applicablePolicySets"; + String PROMOTE = "promote"; + String TARGET = "target"; + String WIRED_BY_IMPL = "wiredByImpl"; + String MULTIPLICITY = "multiplicity"; + String TYPE = "type"; + String ELEMENT = "element"; + String MANY = "many"; + String MUST_SUPPLY = "mustSupply"; + String SOURCE = "source"; + String FILE = "file"; + String URI = "uri"; + String ZERO_ONE = "0..1"; + String ZERO_N = "0..n"; + String ONE_ONE = "1..1"; + String ONE_N = "1..n"; +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeDocumentProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeDocumentProcessor.java new file mode 100644 index 0000000000..8e441f14d3 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeDocumentProcessor.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.assembly.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.validation.Schema; + +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; + +/** + * A contrainingType content handler. + * + * @version $Rev: 635373 $ $Date: 2008-03-09 14:51:51 -0700 (Sun, 09 Mar 2008) $ + */ +public class ConstrainingTypeDocumentProcessor extends BaseAssemblyProcessor implements URLArtifactProcessor { + private XMLInputFactory inputFactory; + private Schema schema; + + /** + * Construct a new constrainingType processor. + * @param factory + * @param policyFactory + * @param staxProcessor + */ + public ConstrainingTypeDocumentProcessor(StAXArtifactProcessor staxProcessor, XMLInputFactory inputFactory) { + super(null, null, staxProcessor); + this.inputFactory = inputFactory; + } + + public ConstrainingType read(URL contributionURL, URI uri, URL url) throws ContributionReadException { + InputStream urlStream = null; + try { + + // Create a stream reader + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + urlStream = connection.getInputStream(); + XMLStreamReader reader = inputFactory.createXMLStreamReader(url.toString(), urlStream); + reader.nextTag(); + + // Read the constrainingType model + ConstrainingType constrainingType = (ConstrainingType)extensionProcessor.read(reader); + + // For debugging purposes, write it back to XML +// if (constrainingType != null) { +// try { +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +// outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); +// extensionProcessor.write(constrainingType, outputFactory.createXMLStreamWriter(bos)); +// Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(bos.toByteArray())); +// OutputFormat format = new OutputFormat(); +// format.setIndenting(true); +// format.setIndent(2); +// XMLSerializer serializer = new XMLSerializer(System.out, format); +// serializer.serialize(document); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + + return constrainingType; + + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } catch (IOException e) { + throw new ContributionReadException(e); + } finally { + try { + if (urlStream != null) { + urlStream.close(); + urlStream = null; + } + } catch (IOException ioe) { + //ignore + } + } + } + + public void resolve(ConstrainingType constrainingType, ModelResolver resolver) throws ContributionResolveException { + extensionProcessor.resolve(constrainingType, resolver); + } + + public String getArtifactType() { + return ".constrainingType"; + } + + public Class getModelType() { + return ConstrainingType.class; + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeModelResolver.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeModelResolver.java new file mode 100644 index 0000000000..8ba293d755 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeModelResolver.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + +/** + * A Model Resolver for ConstrainingType models. + * + * @version $Rev: 572482 $ $Date: 2007-09-03 18:28:31 -0700 (Mon, 03 Sep 2007) $ + */ +public class ConstrainingTypeModelResolver implements ModelResolver { + + private Contribution contribution; + private Map map = new HashMap(); + + public ConstrainingTypeModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) { + this.contribution = contribution; + } + + public void addModel(Object resolved) { + ConstrainingType composite = (ConstrainingType)resolved; + map.put(composite.getName(), composite); + } + + public Object removeModel(Object resolved) { + return map.remove(((ConstrainingType)resolved).getName()); + } + + public T resolveModel(Class modelClass, T unresolved) { + + // Lookup a definition for the given namespace + QName qname = ((ConstrainingType)unresolved).getName(); + ConstrainingType resolved = (ConstrainingType) map.get(qname); + if (resolved != null) { + return modelClass.cast(resolved); + } + + // No definition found, delegate the resolution to the imports + for (Import import_ : this.contribution.getImports()) { + if (import_ instanceof NamespaceImport) { + NamespaceImport namespaceImport = (NamespaceImport)import_; + if (namespaceImport.getNamespace().equals(qname.getNamespaceURI())) { + + // Delegate the resolution to the import resolver + resolved = namespaceImport.getModelResolver().resolveModel(ConstrainingType.class, (ConstrainingType)unresolved); + if (!resolved.isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + } + return (T)unresolved; + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeProcessor.java new file mode 100644 index 0000000000..a4200a3881 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/ConstrainingTypeProcessor.java @@ -0,0 +1,257 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +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.assembly.AbstractContract; +import org.apache.tuscany.sca.assembly.AbstractProperty; +import org.apache.tuscany.sca.assembly.AbstractReference; +import org.apache.tuscany.sca.assembly.AbstractService; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.w3c.dom.Document; + +/** + * A constrainingType processor. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public class ConstrainingTypeProcessor extends BaseAssemblyProcessor implements StAXArtifactProcessor { + + /** + * Construct a new constrainingType processor. + * @param factory + * @param policyFactory + * @param extensionProcessor + */ + public ConstrainingTypeProcessor(AssemblyFactory factory, PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + super(factory, policyFactory, extensionProcessor); + } + + public ConstrainingType read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + ConstrainingType constrainingType = null; + AbstractService abstractService = null; + AbstractReference abstractReference = null; + AbstractProperty abstractProperty = null; + AbstractContract abstractContract = null; + QName name = null; + + // Read the constrainingType document + while (reader.hasNext()) { + int event = reader.getEventType(); + switch (event) { + + case START_ELEMENT: + name = reader.getName(); + + // Read a + if (Constants.CONSTRAINING_TYPE_QNAME.equals(name)) { + constrainingType = assemblyFactory.createConstrainingType(); + constrainingType.setName(new QName(getString(reader, TARGET_NAMESPACE), getString(reader, NAME))); + policyProcessor.readPolicies(constrainingType, reader); + + } else if (Constants.SERVICE_QNAME.equals(name)) { + + // Read a + abstractService = assemblyFactory.createAbstractService(); + abstractContract = abstractService; + abstractService.setName(getString(reader, Constants.NAME)); + constrainingType.getServices().add(abstractService); + policyProcessor.readPolicies(abstractService, reader); + + } else if (Constants.REFERENCE_QNAME.equals(name)) { + + // Read a + abstractReference = assemblyFactory.createAbstractReference(); + abstractContract = abstractReference; + abstractReference.setName(getString(reader, Constants.NAME)); + readMultiplicity(abstractReference, reader); + constrainingType.getReferences().add(abstractReference); + policyProcessor.readPolicies(abstractReference, reader); + + } else if (Constants.PROPERTY_QNAME.equals(name)) { + + // Read a + abstractProperty = assemblyFactory.createAbstractProperty(); + readAbstractProperty(abstractProperty, reader); + + // Read the property value + Document value = readPropertyValue(abstractProperty.getXSDElement(), abstractProperty.getXSDType(), reader); + abstractProperty.setValue(value); + + constrainingType.getProperties().add(abstractProperty); + policyProcessor.readPolicies(abstractProperty, reader); + + } else if (OPERATION.equals(name)) { + + // Read an + Operation operation = new OperationImpl(); + operation.setName(getString(reader, NAME)); + operation.setUnresolved(true); + policyProcessor.readPolicies(abstractContract, operation, reader); + + } else { + + // Read an extension element + Object extension = extensionProcessor.read(reader); + if (extension instanceof InterfaceContract) { + + // and + abstractContract.setInterfaceContract((InterfaceContract)extension); + } else { + + // Add the extension element to the current element + if (abstractContract != null) { + abstractContract.getExtensions().add(extension); + } else { + constrainingType.getExtensions().add(extension); + } + + } + } + break; + + case END_ELEMENT: + name = reader.getName(); + + // Clear current state when reading reaching end element + if (SERVICE_QNAME.equals(name)) { + abstractService = null; + abstractContract = null; + } else if (REFERENCE_QNAME.equals(name)) { + abstractReference = null; + abstractContract = null; + } else if (PROPERTY_QNAME.equals(name)) { + abstractProperty = null; + } + break; + } + if (reader.hasNext()) { + reader.next(); + } + } + return constrainingType; + } + + public void write(ConstrainingType constrainingType, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + // Write element + writeStartDocument(writer, CONSTRAINING_TYPE, + new XAttr(TARGET_NAMESPACE, constrainingType.getName().getNamespaceURI()), + new XAttr(NAME, constrainingType.getName().getLocalPart()), + policyProcessor.writePolicies(constrainingType)); + + // Write elements + for (AbstractService service : constrainingType.getServices()) { + writeStart(writer, SERVICE, new XAttr(NAME, service.getName()), + policyProcessor.writePolicies(service)); + + extensionProcessor.write(service.getInterfaceContract(), writer); + + for (Object extension: service.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (AbstractReference reference : constrainingType.getReferences()) { + writeStart(writer, REFERENCE, new XAttr(NAME, reference.getName()), + policyProcessor.writePolicies(reference)); + + extensionProcessor.write(reference.getInterfaceContract(), writer); + + for (Object extension: reference.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write elements + for (AbstractProperty abstractProperty : constrainingType.getProperties()) { + writeStart(writer, + PROPERTY, + new XAttr(NAME, abstractProperty.getName()), + new XAttr(MUST_SUPPLY, abstractProperty.isMustSupply()), + new XAttr(MANY, abstractProperty.isMany()), + new XAttr(TYPE, abstractProperty.getXSDType()), + new XAttr(ELEMENT, abstractProperty.getXSDElement()), + policyProcessor.writePolicies(abstractProperty)); + + // Write property value + writePropertyValue(abstractProperty.getValue(), abstractProperty.getXSDElement(), abstractProperty.getXSDType(), writer); + + // Write extensions + for (Object extension : abstractProperty.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEnd(writer); + } + + // Write extension elements + for (Object extension: constrainingType.getExtensions()) { + extensionProcessor.write(extension, writer); + } + + writeEndDocument(writer); + } + + public void resolve(ConstrainingType constrainingType, ModelResolver resolver) throws ContributionResolveException { + // Resolve component type services and references + resolveAbstractContracts(constrainingType.getServices(), resolver); + resolveAbstractContracts(constrainingType.getReferences(), resolver); + + resolveIntents(constrainingType.getRequiredIntents(), resolver); + for ( AbstractService service : constrainingType.getServices() ) { + resolveIntents(service.getRequiredIntents(), resolver); + } + + for ( AbstractReference reference : constrainingType.getReferences() ) { + resolveIntents(reference.getRequiredIntents(), resolver); + } + } + + public QName getArtifactType() { + return CONSTRAINING_TYPE_QNAME; + } + + public Class getModelType() { + return ConstrainingType.class; + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/DefaultBeanModelProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/DefaultBeanModelProcessor.java new file mode 100644 index 0000000000..c862a6f127 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/DefaultBeanModelProcessor.java @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +public class DefaultBeanModelProcessor extends BaseAssemblyProcessor implements StAXArtifactProcessor { + + private QName artifactType; + private Class modelClass; + private Object modelFactory; + private Method factoryMethod; + private Map setterMethods = new HashMap(); + private Map getterMethods = new HashMap(); + + public DefaultBeanModelProcessor(AssemblyFactory assemblyFactory, + PolicyFactory policyFactory, + QName artifactType, + Class modelClass, + Object modelFactory) { + super(assemblyFactory, policyFactory, null); + this.artifactType = artifactType; + this.modelClass = modelClass; + this.modelFactory = modelFactory; + + // Introspect the factory class and bean model class + if (modelFactory != null) { + + // Find the model create method + for (Method method: modelFactory.getClass().getMethods()) { + if (method.getName().startsWith("create") && method.getReturnType() == modelClass) { + factoryMethod = method; + break; + } + } + } + + // Index the bean's setter methods + for (Method method: modelClass.getMethods()) { + Method getter; + String name = method.getName(); + if (name.startsWith("set") && name.length() > 3) { + + // Get the corresponding getter method + try { + getter = modelClass.getMethod("get" + name.substring(3)); + } catch (Exception e) { + getter = null; + continue; + } + + // Get the property name + name = name.substring(3); + if (name.length() > 1) { + if (!name.toUpperCase().equals(name)) { + name = name.substring(0, 1).toLowerCase() + name.substring(1); + } + } + } else { + continue; + } + + // Map an uppercase property name to a lowercase attribute name + if (name.toUpperCase().equals(name)) { + name = name.toLowerCase(); + } + + // Trim trailing _ from property names + if (name.endsWith("_")) { + name = name.substring(0, name.length()-1); + } + setterMethods.put(name, method); + getterMethods.put(name, getter); + } + } + + public Object read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + + // Read an element + try { + + // Create a new instance of the model + Object model; + if (modelFactory != null) { + // Invoke the factory create method + model = factoryMethod.invoke(modelFactory); + } else { + // Invoke the model bean class default constructor + model = modelClass.newInstance(); + } + + // Initialize the bean properties with the attributes found in the + // XML element + for (int i = 0, n = reader.getAttributeCount(); i < n; i++) { + String attributeName = reader.getAttributeLocalName(i); + Method setter = setterMethods.get(attributeName); + if (setter != null) { + String value = reader.getAttributeValue(i); + setter.invoke(model, value); + } + } + + // Read policies + policyProcessor.readPolicies(model, reader); + + // FIXME read extension elements + + // By default mark the model object unresolved + if (model instanceof Base) { + ((Base)model).setUnresolved(true); + } + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && artifactType.equals(reader.getName())) { + break; + } + } + return model; + + } catch (Exception e) { + throw new ContributionReadException(e); + } + } + + public void write(Object bean, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + try { + // Write the bean properties as attributes + List attrs = new ArrayList(); + for (Map.Entry entry: getterMethods.entrySet()) { + if (entry.getValue().getReturnType() == String.class) { + String value = (String)entry.getValue().invoke(bean); + attrs.add(new XAttr(entry.getKey(), value)); + } + } + + // Write element + writeStart(writer, artifactType.getNamespaceURI(), artifactType.getLocalPart(), + policyProcessor.writePolicies(bean), new XAttr(null, attrs)); + + writeEnd(writer); + + } catch (Exception e) { + throw new ContributionWriteException(e); + } + } + + public void resolve(Object bean, ModelResolver resolver) throws ContributionResolveException { + + // Resolve and merge the component type associated with an + // implementation model + if (bean instanceof Implementation) { + Implementation implementation = (Implementation)bean; + String uri = implementation.getURI(); + if (uri != null) { + int d = uri.lastIndexOf('.'); + if (d != -1) { + uri = uri.substring(0, d) + ".componentType"; + + // Resolve the component type + ComponentType componentType = assemblyFactory.createComponentType(); + componentType.setURI(uri); + componentType.setUnresolved(true); + + componentType = resolver.resolveModel(ComponentType.class, componentType); + if (componentType != null && !componentType.isUnresolved()) { + + // We found a component type, merge it into the implementation model + implementation.getServices().addAll(componentType.getServices()); + implementation.getReferences().addAll(componentType.getReferences()); + implementation.getProperties().addAll(componentType.getProperties()); + implementation.setConstrainingType(componentType.getConstrainingType()); + + if (implementation instanceof PolicySetAttachPoint && + componentType instanceof PolicySetAttachPoint ) + { + PolicySetAttachPoint policiedImpl = (PolicySetAttachPoint)implementation; + PolicySetAttachPoint policiedCompType = (PolicySetAttachPoint)componentType; + + if ( policiedImpl.getPolicySets() != null) { + policiedImpl.getPolicySets().addAll(policiedCompType.getPolicySets()); + } + if (policiedImpl.getRequiredIntents() != null) { + policiedImpl.getRequiredIntents().addAll(policiedCompType.getRequiredIntents()); + } + } + } + } + } + } + + // Mark the model resolved + if (bean instanceof Base) { + ((Base)bean).setUnresolved(false); + } + } + + public QName getArtifactType() { + return artifactType; + } + + public Class getModelType() { + return modelClass; + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/PolicyAttachPointProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/PolicyAttachPointProcessor.java new file mode 100644 index 0000000000..7fd642221b --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/java/org/apache/tuscany/sca/assembly/xml/PolicyAttachPointProcessor.java @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +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.assembly.Binding; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +public class PolicyAttachPointProcessor extends BaseStAXArtifactProcessor implements Constants { + + private PolicyFactory policyFactory; + + public PolicyAttachPointProcessor(PolicyFactory policyFactory) { + this.policyFactory = policyFactory; + } + + /** + * Read policy intents associated with an operation. + * @param attachPoint + * @param operation + * @param reader + */ + private void readIntents(Object attachPoint, Operation operation, XMLStreamReader reader) { + if (!(attachPoint instanceof IntentAttachPoint)) + return; + IntentAttachPoint intentAttachPoint = (IntentAttachPoint)attachPoint; + String value = reader.getAttributeValue(null, REQUIRES); + if (value != null) { + List requiredIntents = intentAttachPoint.getRequiredIntents(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + Intent intent = policyFactory.createIntent(); + intent.setName(qname); + if (operation != null) { + //FIXME Don't we need to handle intent specification + // on an operation basis? + //intent.getOperations().add(operation); + } + requiredIntents.add(intent); + } + } + } + + /** + * Reads policy intents and policy sets associated with an operation. + * @param attachPoint + * @param operation + * @param reader + */ + public void readPolicies(Object attachPoint, Operation operation, XMLStreamReader reader) { + readIntents(attachPoint, operation, reader); + readPolicySets(attachPoint, operation, reader); + } + + /** + * Reads policy intents and policy sets. + * @param attachPoint + * @param reader + */ + public void readPolicies(Object attachPoint, XMLStreamReader reader) { + readPolicies(attachPoint, null, reader); + } + + /** + * Reads policy sets associated with an operation. + * @param attachPoint + * @param operation + * @param reader + */ + private void readPolicySets(Object attachPoint, Operation operation, XMLStreamReader reader) { + if (!(attachPoint instanceof PolicySetAttachPoint)) { + return; + } + PolicySetAttachPoint policySetAttachPoint = (PolicySetAttachPoint)attachPoint; + String value = reader.getAttributeValue(null, POLICY_SETS); + if (value != null) { + List policySets = policySetAttachPoint.getPolicySets(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(qname); + if (operation != null) { + //FIXME Don't we need to handle policySet specification + // on an operation basis? + //policySet.getOperations().add(operation); + } + policySets.add(policySet); + } + } + + value = reader.getAttributeValue(SCA10_TUSCANY_NS, APPLICABLE_POLICY_SETS); + if (value != null) { + List applicablePolicySets = policySetAttachPoint.getApplicablePolicySets(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(qname); + if (operation != null) { + //FIXME Don't we need to handle policySet specification + // on an operation basis? + //policySet.getOperations().add(operation); + } + applicablePolicySets.add(policySet); + } + } + } + + /** + * Write policies + * @param attachPoint + * @return + */ + XAttr writePolicies(Object attachPoint) throws XMLStreamException { + return writePolicies(attachPoint, (Operation)null); + } + + /** + * Write policies + * @param attachPoint + * @return + */ + public void writePolicyAttributes(Object attachPoint, XMLStreamWriter writer) throws XMLStreamException { + writePolicyAttributes(attachPoint, (Operation)null, writer); + } + + /** + * Write policies + * @param attachPoint + * @return + */ + public void writePolicyPrefixes(Object attachPoint, XMLStreamWriter writer) throws XMLStreamException { + writePolicyPrefixes(attachPoint, (Operation)null, writer); + } + + /** + * Write policies associated with an operation + * @param attachPoint + * @param operation + * @return + */ + XAttr writePolicies(Object attachPoint, Operation operation) { + List attrs =new ArrayList(); + attrs.add(writeIntents(attachPoint, operation)); + attrs.add(writePolicySets(attachPoint, operation)); + return new XAttr(null, attrs); + } + + /** + * Write policies + * @param attachPoint + * @return + */ + public void writePolicyAttributes(Object attachPoint, Operation operation, XMLStreamWriter writer) throws XMLStreamException { + XAttr attr = writePolicies(attachPoint, operation); + attr.write(writer); + } + + /** + * Write policies + * @param attachPoint + * @return + */ + public void writePolicyPrefixes(Object attachPoint, Operation operation, XMLStreamWriter writer) throws XMLStreamException { + XAttr attr = writePolicies(attachPoint, operation); + attr.writePrefix(writer); + } + + /** + * Write policy intents associated with an operation. + * @param attachPoint + * @param operation + */ + private XAttr writeIntents(Object attachPoint, Operation operation) { + if (!(attachPoint instanceof IntentAttachPoint)) { + return null; + } + IntentAttachPoint intentAttachPoint = (IntentAttachPoint)attachPoint; + List qnames = new ArrayList(); + for (Intent intent: intentAttachPoint.getRequiredIntents()) { + qnames.add(intent.getName()); + } + return new XAttr(Constants.REQUIRES, qnames); + } + + /** + * Write policy sets associated with an operation. + * @param attachPoint + * @param operation + */ + private XAttr writePolicySets(Object attachPoint, Operation operation) { + if (!(attachPoint instanceof PolicySetAttachPoint)) { + return null; + } + PolicySetAttachPoint policySetAttachPoint = (PolicySetAttachPoint)attachPoint; + List qnames = new ArrayList(); + for (PolicySet policySet: policySetAttachPoint.getPolicySets()) { + qnames.add(policySet.getName()); + } + return new XAttr(Constants.POLICY_SETS, qnames); + } + + public void resolvePolicies(Object attachPoint, ModelResolver resolver) { + if ( attachPoint instanceof PolicySetAttachPoint ) { + PolicySetAttachPoint policySetAttachPoint = (PolicySetAttachPoint)attachPoint; + + List requiredIntents = new ArrayList(); + Intent resolvedIntent = null; + + if ( policySetAttachPoint.getRequiredIntents() != null && policySetAttachPoint.getRequiredIntents().size() > 0 ) { + for ( Intent intent : policySetAttachPoint.getRequiredIntents() ) { + resolvedIntent = resolver.resolveModel(Intent.class, intent); + requiredIntents.add(resolvedIntent); + } + policySetAttachPoint.getRequiredIntents().clear(); + policySetAttachPoint.getRequiredIntents().addAll(requiredIntents); + } + + if ( policySetAttachPoint.getPolicySets() != null && policySetAttachPoint.getPolicySets().size() > 0 ) { + List resolvedPolicySets = new ArrayList(); + PolicySet resolvedPolicySet = null; + for ( PolicySet policySet : policySetAttachPoint.getPolicySets() ) { + resolvedPolicySet = resolver.resolveModel(PolicySet.class, policySet); + resolvedPolicySets.add(resolvedPolicySet); + } + policySetAttachPoint.getPolicySets().clear(); + policySetAttachPoint.getPolicySets().addAll(resolvedPolicySets); + } + } + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/branches/sca-android/tuscany-assembly-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver new file mode 100644 index 0000000000..ecc34942f1 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver @@ -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. + +org.apache.tuscany.sca.assembly.xml.CompositeModelResolver;model=org.apache.tuscany.sca.assembly.Composite +org.apache.tuscany.sca.assembly.xml.ConstrainingTypeModelResolver;model=org.apache.tuscany.sca.assembly.ConstrainingType +org.apache.tuscany.sca.assembly.xml.ComponentTypeModelResolver;model=org.apache.tuscany.sca.assembly.ComponentType diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/BuildPolicyTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/BuildPolicyTestCase.java new file mode 100644 index 0000000000..360cfbbacc --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/BuildPolicyTestCase.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultURLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsProcessor; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.xml.PolicySetProcessor; +import org.apache.tuscany.sca.policy.xml.ProfileIntentProcessor; +import org.apache.tuscany.sca.policy.xml.QualifiedIntentProcessor; +import org.apache.tuscany.sca.policy.xml.SimpleIntentProcessor; + +/** + * Test reading SCA XML assembly documents. + * + * @version $Rev: 561254 $ $Date: 2007-07-31 13:16:27 +0530 (Tue, 31 Jul 2007) $ + */ +public class BuildPolicyTestCase extends TestCase { + private ExtensibleURLArtifactProcessor documentProcessor; + private TestModelResolver resolver; + private SCADefinitionsDocumentProcessor scaDefnDocProcessor; + private CompositeBuilder compositeBuilder; + private Composite composite; + + @Override + public void setUp() throws Exception { + List scaDefnSink = new ArrayList(); + AssemblyFactory factory = new DefaultAssemblyFactory(); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + resolver = new TestModelResolver(); + compositeBuilder = new CompositeBuilderImpl(factory, new TestSCABindingFactoryImpl(), new DefaultIntentAttachPointTypeFactory(), new InterfaceContractMapperImpl(), null); + URLArtifactProcessorExtensionPoint documentProcessors = new DefaultURLArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors); + + // Create StAX processors + DefaultStAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + ExtensibleStAXArtifactProcessor staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new SCADefinitionsProcessor(policyFactory, staxProcessor, resolver)); + staxProcessors.addArtifactProcessor(new SimpleIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ProfileIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new QualifiedIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new PolicySetProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new MockPolicyProcessor()); + + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + + // Create document processors + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, inputFactory, scaDefnSink)); + documentProcessors.addArtifactProcessor(new ComponentTypeDocumentProcessor(staxProcessor, inputFactory)); + documentProcessors.addArtifactProcessor(new ConstrainingTypeDocumentProcessor(staxProcessor, inputFactory)); + scaDefnDocProcessor = new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, inputFactory, policyFactory); + documentProcessors.addArtifactProcessor(scaDefnDocProcessor); + + URL url = getClass().getResource("CalculatorComponent.constrainingType"); + URI uri = URI.create("CalculatorComponent.constrainingType"); + ConstrainingType constrainingType = (ConstrainingType)documentProcessor.read(null, uri, url); + assertNotNull(constrainingType); + resolver.addModel(constrainingType); + + url = getClass().getResource("TestAllPolicyCalculator.composite"); + uri = URI.create("TestAllCalculator.constrainingType"); + composite = (Composite)documentProcessor.read(null, uri, url); + assertNotNull(composite); + + url = getClass().getResource("another_test_definitions.xml"); + uri = URI.create("another_test_definitions.xml"); + SCADefinitions scaDefns = (SCADefinitions)scaDefnDocProcessor.read(null, uri, url); + assertNotNull(scaDefns); + scaDefnSink.add(scaDefns); + + //preResolvePolicyTests(composite); + documentProcessor.resolve(scaDefns, resolver); + documentProcessor.resolve(composite, resolver); + //postResolvePolicyTests(composite); + + compositeBuilder.build(composite); + } + + @Override + public void tearDown() throws Exception { + documentProcessor = null; + resolver = null; + } + + public void testPolicyIntentInheritance() throws Exception { + String namespaceUri = "http://test"; + + IntentAttachPoint policiedComposite = (IntentAttachPoint)composite; + assertEquals(policiedComposite.getRequiredIntents().size(), 1); + assertEquals(policiedComposite.getRequiredIntents().get(0).getName(), new QName(namespaceUri, "tuscanyIntent_1")); + + //1 defined for composite, 2 defined for the service, 1 defined and 3 inherited for the promoted service (4) + assertEquals(composite.getServices().get(0).getRequiredIntents().size(), 7); + //1 from the operation defined in this service and 2 from the operation defined in the promoted service + assertEquals(composite.getServices().get(0).getConfiguredOperations().get(0).getRequiredIntents().size(), 5); + assertEquals(composite.getServices().get(0).getRequiredIntents().get(3).getName(), new QName(namespaceUri, "tuscanyIntent_3")); + //bindings will have only 2 intents since duplications will be cut out + assertEquals(((IntentAttachPoint)composite.getServices().get(0).getBindings().get(0)).getRequiredIntents().size(), 3); + assertEquals(((OperationsConfigurator)composite.getServices().get(0).getBindings().get(0)).getConfiguredOperations().size(), 1); + assertEquals(((OperationsConfigurator)composite.getServices().get(0).getBindings().get(0)).getConfiguredOperations().get(0).getRequiredIntents().size(), 5); + + assertEquals(composite.getReferences().get(0).getRequiredIntents().size(), 5); + assertEquals(composite.getReferences().get(0).getConfiguredOperations().size(), 1); + assertEquals(composite.getReferences().get(0).getConfiguredOperations().get(0).getRequiredIntents().size(), 4); + assertEquals(composite.getReferences().get(0).getRequiredIntents().get(1).getName(), new QName(namespaceUri, "tuscanyIntent_1")); + assertEquals(((IntentAttachPoint)composite.getReferences().get(0).getBindings().get(0)).getRequiredIntents().size(), 3); + + assertEquals(composite.getComponents().get(0).getRequiredIntents().size(), 3); + assertEquals(composite.getComponents().get(0).getRequiredIntents().get(2).getName(), new QName(namespaceUri, "tuscanyIntent_1")); + assertEquals(composite.getComponents().get(0).getServices().get(0).getRequiredIntents().size(), 4); + assertEquals(composite.getComponents().get(0).getServices().get(0).getCallback().getRequiredIntents().size(), 4); + assertEquals(composite.getComponents().get(0).getServices().get(0).getConfiguredOperations().get(0).getRequiredIntents().size(), 5); + assertEquals(composite.getComponents().get(0).getReferences().get(0).getRequiredIntents().size(), 5); + assertEquals(composite.getComponents().get(0).getReferences().get(0).getConfiguredOperations().get(0).getRequiredIntents().size(), 5); + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/MockPolicyProcessor.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/MockPolicyProcessor.java new file mode 100644 index 0000000000..2ee4abd99a --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/MockPolicyProcessor.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.assembly.xml; + +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.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.Policy; + +public class MockPolicyProcessor implements StAXArtifactProcessor { + + public QName getArtifactType() { + return new QName("http://schemas.xmlsoap.org/ws/2004/09/policy", "PolicyAttachment"); + } + + public Policy read(XMLStreamReader arg0) throws ContributionReadException, XMLStreamException { + return new MockPolicyImplOne(); + } + + public void write(Policy arg0, XMLStreamWriter arg1) throws ContributionWriteException, + XMLStreamException { + } + + public Class getModelType() { + return Policy.class; + } + + public void resolve(Policy arg0, ModelResolver arg1) throws ContributionResolveException { + } + + + public class MockPolicyImplOne implements Policy { + public QName getSchemaName() { + return new QName("http://schemas.xmlsoap.org/ws/2004/09/policy", "PolicyAttachment"); + } + + public boolean isUnresolved() { + return false; + } + + public void setUnresolved(boolean unresolved) { + } + + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadAllTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadAllTestCase.java new file mode 100644 index 0000000000..ffd88cc4a4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadAllTestCase.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.io.InputStream; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Callback; +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.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Test reading SCA XML assemblies. + * + * @version $Rev: 638855 $ $Date: 2008-03-19 08:04:32 -0700 (Wed, 19 Mar 2008) $ + */ +public class ReadAllTestCase extends TestCase { + private ExtensibleStAXArtifactProcessor staxProcessor; + + @Override + public void setUp() throws Exception { + AssemblyFactory factory = new DefaultAssemblyFactory(); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + ContributionFactory contributionFactory = new DefaultContributionFactory(); + + StAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + + staxProcessors.addArtifactProcessor(new CompositeProcessor(contributionFactory, factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor)); + } + + @Override + public void tearDown() throws Exception { + } + + public void testReadComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("TestAllCalculator.composite"); + Composite composite = (Composite)staxProcessor.read(is, Composite.class); + assertNotNull(composite); + assertEquals(composite.getName(), new QName("http://calc", "TestAllCalculator")); + assertEquals(composite.getConstrainingType().getName(), new QName("http://calc", "CalculatorComponent")); + assertTrue(composite.isLocal()); + assertFalse(composite.getAutowire() == Boolean.TRUE); + assertEquals(((PolicySetAttachPoint)composite).getRequiredIntents().get(0).getName(), new QName("http://test", + "confidentiality")); + assertEquals(((PolicySetAttachPoint)composite).getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + + Composite include = composite.getIncludes().get(0); + assertEquals(include.getName(), new QName("http://calc", "TestAllDivide")); + + CompositeService calcCompositeService = (CompositeService)composite.getServices().get(0); + assertEquals(calcCompositeService.getName(), "CalculatorService"); + assertTrue(calcCompositeService.getPromotedService().isUnresolved()); + assertEquals(calcCompositeService.getPromotedService().getName(), + "CalculatorService"); + assertEquals(calcCompositeService.getRequiredIntents().get(0).getName(), + new QName("http://test", "confidentiality")); + assertEquals(calcCompositeService.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + // TODO test operations + Callback calcServiceCallback = calcCompositeService.getCallback(); + assertNotNull(calcServiceCallback); + assertEquals(calcServiceCallback.getRequiredIntents().get(0).getName(), + new QName("http://test", "confidentiality")); + assertEquals(calcServiceCallback.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + // TODO test operations + + Component calcComponent = composite.getComponents().get(0); + assertEquals(calcComponent.getName(), "CalculatorServiceComponent"); + assertEquals(calcComponent.getAutowire(), Boolean.FALSE); + assertEquals(calcComponent.getConstrainingType().getName(), new QName("http://calc", + "CalculatorComponent")); + assertEquals(calcComponent.getRequiredIntents().get(0).getName(), new QName("http://test", + "confidentiality")); + assertEquals(calcComponent.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + + ComponentService calcComponentService = calcComponent.getServices().get(0); + assertEquals(calcComponentService.getName(), "CalculatorService"); + assertEquals(calcComponentService.getRequiredIntents().get(0).getName(), + new QName("http://test", "confidentiality")); + assertEquals(calcComponentService.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + // TODO test operations + + ComponentReference calcComponentReference = calcComponent.getReferences().get(0); + assertEquals(calcComponentReference.getName(), "addService"); + assertEquals(calcComponentReference.getAutowire(), Boolean.FALSE); + assertEquals(calcComponentReference.isWiredByImpl(), false); + assertEquals(calcComponentReference.getRequiredIntents().get(0).getName(), + new QName("http://test", "confidentiality")); + assertEquals(calcComponentReference.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + // TODO test operations + + Property property = calcComponent.getProperties().get(0); + assertEquals(property.getName(), "round"); + Document doc = (Document) property.getValue(); + Element element = doc.getDocumentElement(); + String value = element.getTextContent(); + assertEquals(value, "true"); + assertEquals(property.getXSDType(), new QName("http://www.w3.org/2001/XMLSchema", "boolean")); + assertEquals(property.isMany(), false); + + CompositeReference calcCompositeReference = (CompositeReference)composite.getReferences().get(0); + assertEquals(calcCompositeReference.getName(), "MultiplyService"); + assertTrue(calcCompositeReference.getPromotedReferences().get(0).isUnresolved()); + assertEquals(calcCompositeReference.getPromotedReferences().get(0).getName(), + "CalculatorServiceComponent/multiplyService"); + assertEquals(calcCompositeReference.getRequiredIntents().get(0).getName(), + new QName("http://test", "confidentiality")); + assertEquals(calcCompositeReference.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + // TODO test operations + Callback calcCallback = calcCompositeReference.getCallback(); + assertEquals(calcCompositeReference.getRequiredIntents().get(0).getName(), + new QName("http://test", "confidentiality")); + assertEquals(calcCompositeReference.getPolicySets().get(0).getName(), new QName("http://test", "SecureReliablePolicy")); + assertNotNull(calcCallback); + // TODO test operations + + //new PrintUtil(System.out).print(composite); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadDocumentTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadDocumentTestCase.java new file mode 100644 index 0000000000..4fe068142d --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadDocumentTestCase.java @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import java.net.URI; +import java.net.URL; + +import javax.xml.XMLConstants; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.ValidatorHandler; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultURLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultValidatingXMLInputFactory; +import org.apache.tuscany.sca.contribution.processor.DefaultValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; + +/** + * Test reading SCA XML assembly documents. + * + * @version $Rev: 639226 $ $Date: 2008-03-20 02:45:37 -0700 (Thu, 20 Mar 2008) $ + */ +public class ReadDocumentTestCase extends TestCase { + + private ExtensibleURLArtifactProcessor documentProcessor; + private TestModelResolver resolver; + private XMLInputFactory inputFactory; + private ExtensibleStAXArtifactProcessor staxProcessor; + + @Override + public void setUp() throws Exception { + AssemblyFactory factory = new DefaultAssemblyFactory(); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + + URLArtifactProcessorExtensionPoint documentProcessors = new DefaultURLArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors); + + // Create StAX processors + DefaultStAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor)); + + inputFactory = XMLInputFactory.newInstance(); + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, inputFactory, null)); + documentProcessors.addArtifactProcessor(new ComponentTypeDocumentProcessor(staxProcessor, inputFactory)); + documentProcessors.addArtifactProcessor(new ConstrainingTypeDocumentProcessor(staxProcessor, inputFactory)); + + resolver = new TestModelResolver(); + } + + @Override + public void tearDown() throws Exception { + } + + public void testValidateAssembly() throws Exception { + + SchemaFactory schemaFactory; + try { + schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + } catch (Error e) { + // Some old JDKs don't support XMLSchema validation + return; + } catch (Exception e) { + // Some old JDKs don't support XMLSchema validation + return; + } + Schema schema = schemaFactory.newSchema(getClass().getClassLoader().getResource("tuscany-sca.xsd")); + ValidatorHandler handler = schema.newValidatorHandler(); + + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + URL url = getClass().getResource("Calculator.composite"); + XMLReader reader = parserFactory.newSAXParser().getXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setContentHandler(handler); + reader.parse(new InputSource(url.openStream())); + } + + public void testValidateImplementation() throws Exception { + + SchemaFactory schemaFactory; + try { + schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + } catch (Error e) { + // Some old JDKs don't support XMLSchema validation + return; + } catch (Exception e) { + // Some old JDKs don't support XMLSchema validation + return; + } + Schema schema = schemaFactory.newSchema(getClass().getClassLoader().getResource("tuscany-sca.xsd")); + ValidatorHandler handler = schema.newValidatorHandler(); + + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + URL url = getClass().getResource("JavaScriptReference.composite"); + XMLReader reader = parserFactory.newSAXParser().getXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setContentHandler(handler); + reader.parse(new InputSource(url.openStream())); + } + + public void testReadImplementation() throws Exception { + + ValidationSchemaExtensionPoint schemas = new DefaultValidationSchemaExtensionPoint(); + schemas.addSchema(getClass().getClassLoader().getResource("tuscany-sca.xsd").toString()); + XMLInputFactory validatingInputFactory = new DefaultValidatingXMLInputFactory(inputFactory, schemas); + CompositeDocumentProcessor compositeDocumentProcessor = new CompositeDocumentProcessor(staxProcessor, validatingInputFactory, null); + + URL url = getClass().getResource("JavaScriptReference.composite"); + URI uri = URI.create("JavaScriptReference.composite"); + Composite composite = (Composite)compositeDocumentProcessor.read(null, uri, url); + assertNotNull(composite); + } + + public void testValidateBinding() throws Exception { + + SchemaFactory schemaFactory; + try { + schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + } catch (Error e) { + // Some old JDKs don't support XMLSchema validation + return; + } catch (Exception e) { + // Some old JDKs don't support XMLSchema validation + return; + } + Schema schema = schemaFactory.newSchema(getClass().getClassLoader().getResource("tuscany-sca.xsd")); + ValidatorHandler handler = schema.newValidatorHandler(); + + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + URL url = getClass().getResource("RMIBindingTest.composite"); + XMLReader reader = parserFactory.newSAXParser().getXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setContentHandler(handler); + reader.parse(new InputSource(url.openStream())); + } + + public void testReadBinding() throws Exception { + + ValidationSchemaExtensionPoint schemas = new DefaultValidationSchemaExtensionPoint(); + schemas.addSchema(getClass().getClassLoader().getResource("tuscany-sca.xsd").toString()); + XMLInputFactory validatingInputFactory = new DefaultValidatingXMLInputFactory(inputFactory, schemas); + CompositeDocumentProcessor compositeDocumentProcessor = new CompositeDocumentProcessor(staxProcessor, validatingInputFactory, null); + + URL url = getClass().getResource("RMIBindingTest.composite"); + URI uri = URI.create("RMIBindingTest.composite"); + Composite composite = (Composite)compositeDocumentProcessor.read(null, uri, url); + assertNotNull(composite); + } + + public void testResolveConstrainingType() throws Exception { + + URL url = getClass().getResource("CalculatorComponent.constrainingType"); + URI uri = URI.create("CalculatorComponent.constrainingType"); + ConstrainingType constrainingType = (ConstrainingType)documentProcessor.read(null, uri, url); + assertNotNull(constrainingType); + resolver.addModel(constrainingType); + + url = getClass().getResource("TestAllCalculator.composite"); + uri = URI.create("TestAllCalculator.constrainingType"); + Composite composite = (Composite)documentProcessor.read(null, uri, url); + assertNotNull(composite); + + documentProcessor.resolve(composite, resolver); + + assertEquals(composite.getConstrainingType(), constrainingType); + assertEquals(composite.getComponents().get(0).getConstrainingType(), constrainingType); + } + + public void testResolveComposite() throws Exception { + URL url = getClass().getResource("Calculator.composite"); + URI uri = URI.create("Calculator.composite"); + Composite nestedComposite = (Composite)documentProcessor.read(null, uri, url); + assertNotNull(nestedComposite); + resolver.addModel(nestedComposite); + + url = getClass().getResource("TestAllCalculator.composite"); + uri = URI.create("TestAllCalculator.composite"); + Composite composite = (Composite)documentProcessor.read(null, uri, url); + + documentProcessor.resolve(composite, resolver); + + assertEquals(composite.getComponents().get(2).getImplementation(), nestedComposite); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadTestCase.java new file mode 100644 index 0000000000..5ead95df9d --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ReadTestCase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Test reading SCA XML assemblies. + * + * @version $Rev: 638855 $ $Date: 2008-03-19 08:04:32 -0700 (Wed, 19 Mar 2008) $ + */ +public class ReadTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private DefaultStAXArtifactProcessorExtensionPoint staxProcessors; + private ExtensibleStAXArtifactProcessor staxProcessor; + private AssemblyFactory factory; + private PolicyFactory policyFactory; + + @Override + public void setUp() throws Exception { + factory = new DefaultAssemblyFactory(); + policyFactory = new DefaultPolicyFactory(); + inputFactory = XMLInputFactory.newInstance(); + staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + } + + @Override + public void tearDown() throws Exception { + } + + public void testReadComponentType() throws Exception { + ComponentTypeProcessor componentTypeReader = new ComponentTypeProcessor(factory, policyFactory, staxProcessor); + InputStream is = getClass().getResourceAsStream("CalculatorImpl.componentType"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + assertNotNull(componentTypeReader.read(reader)); + is.close(); + } + + public void testReadConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + ConstrainingTypeProcessor constrainingTypeReader = new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + assertNotNull(constrainingTypeReader.read(reader)); + is.close(); + + } + + public void testReadComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + CompositeProcessor compositeReader = new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + assertNotNull(compositeReader.read(reader)); + is.close(); + + } + + public void testReadCompositeAndWireIt() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + CompositeProcessor compositeReader = new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + assertNotNull(compositeReader.read(reader)); + is.close(); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolvePolicyTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolvePolicyTestCase.java new file mode 100644 index 0000000000..6db364950a --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolvePolicyTestCase.java @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultURLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsProcessor; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.xml.PolicySetProcessor; +import org.apache.tuscany.sca.policy.xml.ProfileIntentProcessor; +import org.apache.tuscany.sca.policy.xml.QualifiedIntentProcessor; +import org.apache.tuscany.sca.policy.xml.SimpleIntentProcessor; + +/** + * Test reading SCA XML assembly documents. + * + * @version $Rev: 561254 $ $Date: 2007-07-31 13:16:27 +0530 (Tue, 31 Jul 2007) $ + */ +public class ResolvePolicyTestCase extends TestCase { + + private ExtensibleURLArtifactProcessor documentProcessor; + private TestModelResolver resolver; + SCADefinitionsDocumentProcessor scaDefnDocProcessor; + + @Override + public void setUp() throws Exception { + List scaDefnSink = new ArrayList(); + AssemblyFactory factory = new DefaultAssemblyFactory(); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + resolver = new TestModelResolver(); + + URLArtifactProcessorExtensionPoint documentProcessors = new DefaultURLArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors); + + // Create StAX processors + DefaultStAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + ExtensibleStAXArtifactProcessor staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new SCADefinitionsProcessor(policyFactory, staxProcessor, resolver)); + staxProcessors.addArtifactProcessor(new SimpleIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ProfileIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new QualifiedIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new PolicySetProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new MockPolicyProcessor()); + + // Create document processors + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, inputFactory, scaDefnSink)); + documentProcessors.addArtifactProcessor(new ComponentTypeDocumentProcessor(staxProcessor, inputFactory)); + documentProcessors.addArtifactProcessor(new ConstrainingTypeDocumentProcessor(staxProcessor, inputFactory)); + scaDefnDocProcessor = new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, inputFactory, policyFactory); + documentProcessors.addArtifactProcessor(scaDefnDocProcessor); + } + + @Override + public void tearDown() throws Exception { + } + + public void testResolveConstrainingType() throws Exception { + + URL url = getClass().getResource("CalculatorComponent.constrainingType"); + URI uri = URI.create("CalculatorComponent.constrainingType"); + ConstrainingType constrainingType = (ConstrainingType)documentProcessor.read(null, uri, url); + assertNotNull(constrainingType); + resolver.addModel(constrainingType); + + url = getClass().getResource("TestAllCalculator.composite"); + uri = URI.create("TestAllCalculator.constrainingType"); + Composite composite = (Composite)documentProcessor.read(null, uri, url); + assertNotNull(composite); + + url = getClass().getResource("test_definitions.xml"); + uri = URI.create("test_definitions.xml"); + SCADefinitions scaDefns = (SCADefinitions)scaDefnDocProcessor.read(null, uri, url); + assertNotNull(scaDefns); + + preResolvePolicyTests(composite); + documentProcessor.resolve(scaDefns, resolver); + documentProcessor.resolve(composite, resolver); + postResolvePolicyTests(composite); + + assertEquals(composite.getConstrainingType(), constrainingType); + assertEquals(composite.getComponents().get(0).getConstrainingType(), constrainingType); + } + + private void preResolvePolicyTests(Composite composite) { + assertNull(((PolicySetAttachPoint)composite).getRequiredIntents().get(0).getDescription()); + assertTrue(((PolicySetAttachPoint)composite).getPolicySets().get(0).getProvidedIntents().isEmpty()); + + assertNull(composite.getServices().get(0).getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getServices().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNull(composite.getServices().get(0).getCallback().getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getServices().get(0).getCallback().getPolicySets().get(0).getProvidedIntents().isEmpty()); + + assertNull(composite.getComponents().get(0).getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getComponents().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNull(composite.getComponents().get(0).getServices().get(0).getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getComponents().get(0).getServices().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNull(composite.getComponents().get(0).getReferences().get(0).getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getComponents().get(0).getReferences().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + + assertNull(composite.getReferences().get(0).getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getReferences().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNull(composite.getReferences().get(0).getCallback().getRequiredIntents().get(0).getDescription()); + assertTrue(composite.getReferences().get(0).getCallback().getPolicySets().get(0).getProvidedIntents().isEmpty()); + } + + private void postResolvePolicyTests(Composite composite) { + assertNotNull(((PolicySetAttachPoint)composite).getRequiredIntents().get(0).getDescription()); + assertFalse(((PolicySetAttachPoint)composite).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(((PolicySetAttachPoint)composite).getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + + assertNotNull(composite.getServices().get(0).getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getServices().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getServices().get(0).getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + assertNotNull(composite.getServices().get(0).getCallback().getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getServices().get(0).getCallback().getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getServices().get(0).getCallback().getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + + assertNotNull(composite.getComponents().get(0).getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getComponents().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getComponents().get(0).getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + assertNotNull(composite.getComponents().get(0).getServices().get(0).getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getComponents().get(0).getServices().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getComponents().get(0).getServices().get(0).getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + assertNotNull(composite.getComponents().get(0).getReferences().get(0).getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getComponents().get(0).getReferences().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getComponents().get(0).getReferences().get(0).getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + + assertNotNull(composite.getReferences().get(0).getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getReferences().get(0).getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getReferences().get(0).getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + assertNotNull(composite.getReferences().get(0).getCallback().getRequiredIntents().get(0).getDescription()); + assertFalse(composite.getReferences().get(0).getCallback().getPolicySets().get(0).getProvidedIntents().isEmpty()); + assertNotNull(composite.getReferences().get(0).getCallback().getPolicySets().get(0).getProvidedIntents().get(1).getDescription()); + + + } + + public void testResolveComposite() throws Exception { + URL url = getClass().getResource("Calculator.composite"); + URI uri = URI.create("Calculator.composite"); + Composite nestedComposite = (Composite)documentProcessor.read(null, uri, url); + assertNotNull(nestedComposite); + resolver.addModel(nestedComposite); + + url = getClass().getResource("TestAllCalculator.composite"); + uri = URI.create("TestAllCalculator.composite"); + Composite composite = (Composite)documentProcessor.read(null, uri, url); + + documentProcessor.resolve(composite, resolver); + + assertEquals(composite.getComponents().get(2).getImplementation(), nestedComposite); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolveTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolveTestCase.java new file mode 100644 index 0000000000..6f0ef3ad96 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/ResolveTestCase.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.assembly.xml; + +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Test resolving SCA XML assemblies. + * + * @version $Rev: 638855 $ $Date: 2008-03-19 08:04:32 -0700 (Wed, 19 Mar 2008) $ + */ +public class ResolveTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private DefaultStAXArtifactProcessorExtensionPoint staxProcessors; + private ExtensibleStAXArtifactProcessor staxProcessor; + private TestModelResolver resolver; + private AssemblyFactory factory; + private PolicyFactory policyFactory; + + @Override + public void setUp() throws Exception { + factory = new DefaultAssemblyFactory(); + policyFactory = new DefaultPolicyFactory(); + inputFactory = XMLInputFactory.newInstance(); + staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + resolver = new TestModelResolver(); + } + + @Override + public void tearDown() throws Exception { + } + + public void testResolveConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + ConstrainingTypeProcessor constrainingTypeReader = new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + ConstrainingType constrainingType = constrainingTypeReader.read(reader); + is.close(); + assertNotNull(constrainingType); + resolver.addModel(constrainingType); + + is = getClass().getResourceAsStream("TestAllCalculator.composite"); + CompositeProcessor compositeReader = new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor); + reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeReader.read(reader); + is.close(); + assertNotNull(composite); + + compositeReader.resolve(composite, resolver); + + assertEquals(composite.getConstrainingType(), constrainingType); + assertEquals(composite.getComponents().get(0).getConstrainingType(), constrainingType); + } + + public void testResolveComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + CompositeProcessor compositeReader = new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite nestedComposite = compositeReader.read(reader); + is.close(); + assertNotNull(nestedComposite); + resolver.addModel(nestedComposite); + + is = getClass().getResourceAsStream("TestAllCalculator.composite"); + compositeReader = new CompositeProcessor(new DefaultContributionFactory(), factory, policyFactory, staxProcessor); + reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeReader.read(reader); + is.close(); + + compositeReader.resolve(composite, resolver); + + assertEquals(composite.getComponents().get(2).getImplementation(), nestedComposite); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestModelResolver.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestModelResolver.java new file mode 100644 index 0000000000..5b9292cb17 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestModelResolver.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.assembly.xml; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A default implementation of an artifact resolver, based on a map. + * + * @version $Rev: 560306 $ $Date: 2007-07-27 09:31:44 -0700 (Fri, 27 Jul 2007) $ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map map = new HashMap(); + + public TestModelResolver() { + } + + public T resolveModel(Class modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved) { + return map.remove(resolved); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingFactoryImpl.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingFactoryImpl.java new file mode 100644 index 0000000000..b28a01e156 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingFactoryImpl.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.assembly.xml; + +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; + +/** + * A factory for the SCA binding model. + * + * @version $Rev: 563772 $ $Date: 2007-08-07 23:50:49 -0700 (Tue, 07 Aug 2007) $ + */ +public class TestSCABindingFactoryImpl implements SCABindingFactory { + public SCABinding createSCABinding() { + return new TestSCABindingImpl(); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingImpl.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingImpl.java new file mode 100644 index 0000000000..acbd44dbc9 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/TestSCABindingImpl.java @@ -0,0 +1,213 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * A test cheel for the SCA binding. + * + * @version $Rev: 620307 $ $Date: 2008-02-10 10:56:51 -0800 (Sun, 10 Feb 2008) $ + */ +public class TestSCABindingImpl implements SCABinding, OptimizableBinding, PolicySetAttachPoint, OperationsConfigurator { + private String name; + private String uri; + private List extensions = new ArrayList(); + + private Component targetComponent; + private ComponentService targetComponentService; + private Binding targetBinding; + + List requiredIntents = new ArrayList(); + List policySets = new ArrayList(); + IntentAttachPointType bindingType = new TestSCABindingType(); + List configuredOperations = new ArrayList(); + private List applicablePolicySets = new ArrayList(); + + /** + * Constructs a new SCA binding. + */ + protected TestSCABindingImpl() { + } + + public String getName() { + return name; + } + + public String getURI() { + return uri; + } + + public void setName(String name) { + this.name = name; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public List getExtensions() { + return extensions; + } + + public boolean isUnresolved() { + return false; + } + + public void setUnresolved(boolean unresolved) { + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + /** + * @return the targetComponent + */ + public Component getTargetComponent() { + return targetComponent; + } + + /** + * @param targetComponent the targetComponent to set + */ + public void setTargetComponent(Component targetComponent) { + this.targetComponent = targetComponent; + } + + /** + * @return the targetComponentService + */ + public ComponentService getTargetComponentService() { + return targetComponentService; + } + + /** + * @param targetComponentService the targetComponentService to set + */ + public void setTargetComponentService(ComponentService targetComponentService) { + this.targetComponentService = targetComponentService; + } + + /** + * @return the targetBinding + */ + public Binding getTargetBinding() { + return targetBinding; + } + + /** + * @param targetBinding the targetBinding to set + */ + public void setTargetBinding(Binding targetBinding) { + this.targetBinding = targetBinding; + } + + public List getPolicySets() { + // TODO Auto-generated method stub + return policySets; + } + + public List getRequiredIntents() { + // TODO Auto-generated method stub + return requiredIntents; + } + + public IntentAttachPointType getType() { + // TODO Auto-generated method stub + return bindingType; + } + + public void setType(IntentAttachPointType type) { + this.bindingType = type; + } + + private class TestSCABindingType implements IntentAttachPointType { + private QName name = new QName("http://www.osoa.org/xmlns/sca/1.0","binding"); + + public List getAlwaysProvidedIntents() { + // TODO Auto-generated method stub + return null; + } + + public List getMayProvideIntents() { + // TODO Auto-generated method stub + return null; + } + + public QName getName() { + return name; + } + + public boolean isUnresolved() { + // TODO Auto-generated method stub + return false; + } + + public void setName(QName type) { + // TODO Auto-generated method stub + + } + + public void setUnresolved(boolean unresolved) { + // TODO Auto-generated method stub + + } + + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } + + public List getConfiguredOperations() { + return configuredOperations; + } + + public void setConfiguredOperations(List configuredOperations) { + this.configuredOperations = configuredOperations; + } + + public List getApplicablePolicySets() { + return applicablePolicySets; + } +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WireTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WireTestCase.java new file mode 100644 index 0000000000..8512dcefa1 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WireTestCase.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.xml; + +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Test the wiring of SCA XML assemblies. + * + * @version $Rev: 637129 $ $Date: 2008-03-14 08:11:59 -0700 (Fri, 14 Mar 2008) $ + */ +public class WireTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private DefaultStAXArtifactProcessorExtensionPoint staxProcessors; + private ExtensibleStAXArtifactProcessor staxProcessor; + private TestModelResolver resolver; + private AssemblyFactory assemblyFactory; + private SCABindingFactory scaBindingFactory; + private PolicyFactory policyFactory; + private InterfaceContractMapper mapper; + private SCADefinitionsDocumentProcessor scaDefnDocProcessor; + + @Override + public void setUp() throws Exception { + inputFactory = XMLInputFactory.newInstance(); + staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + resolver = new TestModelResolver(); + assemblyFactory = new DefaultAssemblyFactory(); + scaBindingFactory = new TestSCABindingFactoryImpl(); + policyFactory = new DefaultPolicyFactory(); + mapper = new InterfaceContractMapperImpl(); + + scaDefnDocProcessor = new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, inputFactory, policyFactory); + + } + + @Override + public void tearDown() throws Exception { + } + + public void testResolveConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + ConstrainingTypeProcessor constrainingTypeReader = new ConstrainingTypeProcessor(assemblyFactory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + ConstrainingType constrainingType = constrainingTypeReader.read(reader); + is.close(); + assertNotNull(constrainingType); + resolver.addModel(constrainingType); + + is = getClass().getResourceAsStream("TestAllCalculator.composite"); + CompositeProcessor compositeReader = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeReader.read(reader); + is.close(); + assertNotNull(composite); + + URL url = getClass().getResource("test_definitions.xml"); + URI uri = URI.create("test_definitions.xml"); + SCADefinitions scaDefns = (SCADefinitions)scaDefnDocProcessor.read(null, uri, url); + assertNotNull(scaDefns); + + scaDefnDocProcessor.resolve(scaDefns, resolver); + + compositeReader.resolve(composite, resolver); + CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, new DefaultIntentAttachPointTypeFactory(), mapper, null); + compositeUtil.build(composite); + + assertEquals(composite.getConstrainingType(), constrainingType); + assertEquals(composite.getComponents().get(0).getConstrainingType(), constrainingType); + } + + public void testResolveComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + CompositeProcessor compositeReader = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite nestedComposite = compositeReader.read(reader); + is.close(); + assertNotNull(nestedComposite); + resolver.addModel(nestedComposite); + + is = getClass().getResourceAsStream("TestAllCalculator.composite"); + compositeReader = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeReader.read(reader); + is.close(); + + URL url = getClass().getResource("test_definitions.xml"); + URI uri = URI.create("test_definitions.xml"); + SCADefinitions scaDefns = (SCADefinitions)scaDefnDocProcessor.read(null, uri, url); + assertNotNull(scaDefns); + + scaDefnDocProcessor.resolve(scaDefns, resolver); + + compositeReader.resolve(composite, resolver); + CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, new DefaultIntentAttachPointTypeFactory(), mapper, null); + compositeUtil.build(composite); + + assertEquals(composite.getComponents().get(2).getImplementation(), nestedComposite); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WriteAllTestCase.java b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WriteAllTestCase.java new file mode 100644 index 0000000000..aa95b98a31 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/java/org/apache/tuscany/sca/assembly/xml/WriteAllTestCase.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Test writing SCA XML assemblies. + * + * @version $Rev: 637129 $ $Date: 2008-03-14 08:11:59 -0700 (Fri, 14 Mar 2008) $ + */ +public class WriteAllTestCase extends TestCase { + private DefaultStAXArtifactProcessorExtensionPoint staxProcessors; + private ExtensibleStAXArtifactProcessor staxProcessor; + private TestModelResolver resolver; + private AssemblyFactory assemblyFactory; + private SCABindingFactory scaBindingFactory; + private PolicyFactory policyFactory; + private InterfaceContractMapper mapper; + private CompositeBuilderImpl compositeUtil; + private SCADefinitionsDocumentProcessor scaDefnDocProcessor; + + + @Override + public void setUp() throws Exception { + assemblyFactory = new DefaultAssemblyFactory(); + scaBindingFactory = new TestSCABindingFactoryImpl(); + policyFactory = new DefaultPolicyFactory(); + mapper = new InterfaceContractMapperImpl(); + compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, new DefaultIntentAttachPointTypeFactory(), mapper, null); + staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(assemblyFactory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(assemblyFactory, policyFactory, staxProcessor)); + resolver = new TestModelResolver(); + scaDefnDocProcessor = new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, XMLInputFactory.newInstance(), policyFactory); + } + + @Override + public void tearDown() throws Exception { + } + + public void testReadWriteComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("TestAllCalculator.composite"); + Composite composite = staxProcessor.read(is, Composite.class); + + verifyComposite(composite); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(composite, bos); + bos.close(); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + composite = staxProcessor.read(bis, Composite.class); + + verifyComposite(composite); + + } + + public void testReadWireWriteComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("TestAllCalculator.composite"); + Composite composite = staxProcessor.read(is, Composite.class); + + URL url = getClass().getResource("test_definitions.xml"); + URI uri = URI.create("test_definitions.xml"); + SCADefinitions scaDefns = (SCADefinitions)scaDefnDocProcessor.read(null, uri, url); + assertNotNull(scaDefns); + scaDefnDocProcessor.resolve(scaDefns, resolver); + + staxProcessor.resolve(composite, resolver); + compositeUtil.build(composite); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(composite, bos); + } + + public void testReadWriteComponentType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorImpl.componentType"); + ComponentType componentType = staxProcessor.read(is, ComponentType.class); + staxProcessor.resolve(componentType, resolver); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(componentType, bos); + } + + public void testReadWriteConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + ConstrainingType constrainingType = staxProcessor.read(is, ConstrainingType.class); + staxProcessor.resolve(constrainingType, resolver); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(constrainingType, bos); + } + + private void verifyComposite(Composite composite) { + assertEquals(composite.getProperties().get(0).getName(),"prop1"); + assertEquals(composite.getProperties().get(0).isMany(), true); + assertEquals(composite.getProperties().get(1).getName(),"prop2"); + assertEquals(composite.getProperties().get(1).isMustSupply(), true); + assertEquals(composite.getProperties().get(0).getXSDType(), new QName("http://foo", "MyComplexType")); + assertEquals(composite.getProperties().get(1).getXSDElement(), new QName("http://www.osoa.org/xmlns/sca/1.0", "MyComplexPropertyValue1")); + } + +} diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/Calculator.composite b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/Calculator.composite new file mode 100644 index 0000000000..4546fddb2d --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/Calculator.composite @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorComponent.constrainingType b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorComponent.constrainingType new file mode 100644 index 0000000000..072fe8fde1 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorComponent.constrainingType @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorImpl.componentType b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorImpl.componentType new file mode 100644 index 0000000000..2dbecdabb7 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/CalculatorImpl.componentType @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/JavaScriptReference.composite b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/JavaScriptReference.composite new file mode 100644 index 0000000000..a313dd1e6d --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/JavaScriptReference.composite @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/RMIBindingTest.composite b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/RMIBindingTest.composite new file mode 100644 index 0000000000..2da2b56e8e --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/RMIBindingTest.composite @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllCalculator.composite b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllCalculator.composite new file mode 100644 index 0000000000..5091ff700b --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllCalculator.composite @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AValue + InterestingURI + + + BValue + BoringURI + + + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllDivide.composite b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllDivide.composite new file mode 100644 index 0000000000..0e7a48c698 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllDivide.composite @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllPolicyCalculator.composite b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllPolicyCalculator.composite new file mode 100644 index 0000000000..7bc7ccdb83 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/TestAllPolicyCalculator.composite @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AValue + InterestingURI + + + BValue + BoringURI + + + + diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/another_test_definitions.xml b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/another_test_definitions.xml new file mode 100644 index 0000000000..bcc8c54dc8 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/another_test_definitions.xml @@ -0,0 +1,97 @@ + + + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/test_definitions.xml b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/test_definitions.xml new file mode 100644 index 0000000000..b79cb6b7b7 --- /dev/null +++ b/branches/sca-android/tuscany-assembly-xml/src/test/resources/org/apache/tuscany/sca/assembly/xml/test_definitions.xml @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ... + + + + ... + + + + + + + + + Protect messages from unauthorized reading or modification + + + + + + Protect messages from unauthorized reading or modification + + + + + + + Communitcation thro this binding must prevent + unauthorized users from reading the messages. + + + + + + Communitcation thro this binding must prevent + unauthorized modification of the messages. + + + + + + Communitcation thro this binding required + Authentication. + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly/.classpath b/branches/sca-android/tuscany-assembly/.classpath new file mode 100644 index 0000000000..9c1dfd40f1 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly/.project b/branches/sca-android/tuscany-assembly/.project new file mode 100644 index 0000000000..334e14be4d --- /dev/null +++ b/branches/sca-android/tuscany-assembly/.project @@ -0,0 +1,18 @@ + + tuscany-assembly + Parent POM defining settings that can be used across Tuscany + + tuscany-definitions + tuscany-extensibility + tuscany-policy + tuscany-interface + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-assembly/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..798d84aa9b --- /dev/null +++ b/branches/sca-android/tuscany-assembly/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:19:29 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-assembly/DISCLAIMER b/branches/sca-android/tuscany-assembly/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-assembly/LICENSE b/branches/sca-android/tuscany-assembly/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/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/branches/sca-android/tuscany-assembly/NOTICE b/branches/sca-android/tuscany-assembly/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-assembly/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-assembly/pom.xml b/branches/sca-android/tuscany-assembly/pom.xml new file mode 100644 index 0000000000..b34e5d21a1 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/pom.xml @@ -0,0 +1,50 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-assembly + Apache Tuscany SCA Assembly Model + + + + org.apache.tuscany.sca + tuscany-policy + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-definitions + 2.0-incubating-SNAPSHOT + + + diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractContract.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractContract.java new file mode 100644 index 0000000000..a234083bef --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractContract.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.policy.IntentAttachPoint; + +/** + * Interface contracts define one or more business functions. These business + * functions are provided by services and are used by references. + * + * @version $Rev: 598005 $ $Date: 2007-11-25 08:36:27 -0800 (Sun, 25 Nov 2007) $ + */ +public interface AbstractContract extends Base, Extensible, IntentAttachPoint, OperationsConfigurator { + + /** + * Returns the name of the contract. + * + * @return the name of the contract + */ + String getName(); + + /** + * Sets the name of the contract. + * + * @param name the name of the contract + */ + void setName(String name); + + /** + * Returns the interface contract defining the interface and callback + * interface for the contract. + * + * @return the interface contract + */ + InterfaceContract getInterfaceContract(); + + /** + * Sets the interface contract defining the interface and callback + * interface for the contract. + * + * @param interfaceContract the interface contract + */ + void setInterfaceContract(InterfaceContract interfaceContract); + + /** + * Returns true if this contract is a reference or service created internally + * to handle a callback interface of another contract, false otherwise. + * + * @return true for a callback contract, false otherwise + */ + boolean isCallback(); + + /** + * Sets a flag indicating whether this is a callback contract. + * + * @param isCallback true for a callback contract, false otherwise + */ + void setIsCallback(boolean isCallback); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractProperty.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractProperty.java new file mode 100644 index 0000000000..514106208d --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractProperty.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.policy.IntentAttachPoint; + +/** + * A property allows for the configuration of an implementation with externally + * set data values. An implementation can have zero or more properties. Each + * property has a data type, which may be either simple or complex. An + * implementation may also define a default value for a property. + */ +public interface AbstractProperty extends Base, Extensible, IntentAttachPoint { + + /** + * Returns the property name. + * + * @return the property name + */ + String getName(); + + /** + * Sets the property name. + * + * @param name the property name + */ + void setName(String name); + + /** + * Returns the default value of the property. + * + * @return the default value of this property + */ + Object getValue(); + + /** + * Sets the default value of the property. + * + * @param defaultValue the default value of this property + */ + void setValue(Object defaultValue); + + /** + * Returns true if the property allows multiple values. + * + * @return true if the property allows multiple values + */ + boolean isMany(); + + /** + * Sets whether or not the property allows multiple values. + * + * @param many true if the property should allow multiple values + */ + void setMany(boolean many); + + /** + * Returns true if a value must be supplied for the property. + * + * @return true is a value must be supplied for the property + */ + boolean isMustSupply(); + + /** + * Sets whether a value must be supplied for the property. + * + * @param mustSupply set to true to require that a value be supplied for + * uses of this property + */ + void setMustSupply(boolean mustSupply); + + /** + * Returns the data type of this property. This is the qualified name of an + * XML schema type. + * + * @return the type of this property + */ + QName getXSDType(); + + /** + * Sets the data type of this property. This is the qualified name of an XML + * schema type. + * + * @param type the type of this property + */ + void setXSDType(QName type); + + /** + * Returns the element defining the data type of this property. This is the + * qualified name of an XML schema element. + * + * @return the element defining the type of this property + */ + QName getXSDElement(); + + /** + * Sets the element defining the data type of this property. This is the + * qualified name of an XML schema element. + * + * @param element the element defining the type of this property + */ + void setXSDElement(QName element); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractReference.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractReference.java new file mode 100644 index 0000000000..9cdb51dad0 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractReference.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.assembly; + +/** + * Represents a reference contract. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public interface AbstractReference extends AbstractContract { + + /** + * Returns the multiplicity allowed for wires connected to this reference. + * + * @return the multiplicity allowed for wires connected to this reference + */ + Multiplicity getMultiplicity(); + + /** + * Sets the multiplicity allowed for wires connected to this reference. + * + * @param multiplicity the multiplicity allowed for wires connected to this + * reference + */ + void setMultiplicity(Multiplicity multiplicity); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractService.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractService.java new file mode 100644 index 0000000000..13e69cef36 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AbstractService.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +/** + * Represents a service contract. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public interface AbstractService extends AbstractContract { + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AssemblyFactory.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AssemblyFactory.java new file mode 100644 index 0000000000..04f0dd8b47 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/AssemblyFactory.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + + +/** + * A factory for the assembly model + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public interface AssemblyFactory { + + /** + * Create a new abstract property. + * + * @return a new abstract property + */ + AbstractProperty createAbstractProperty(); + + /** + * Create a new abstract reference. + * + * @return a new abstract reference + */ + AbstractReference createAbstractReference(); + + /** + * Create a new abstract service. + * + * @return a new abstract service + */ + AbstractService createAbstractService(); + + /** + * Create a new callback. + * + * @return + */ + Callback createCallback(); + + /** + * Create a new component. + * + * @return a new component + */ + Component createComponent(); + + /** + * Create a new component property. + * + * @return a new component property + */ + ComponentProperty createComponentProperty(); + + /** + * Create a new component reference. + * + * @return a new component reference + */ + ComponentReference createComponentReference(); + + /** + * Create a new component service. + * + * @return a new component service + */ + ComponentService createComponentService(); + + /** + * Create a new component type + * + * @return a new component type + */ + ComponentType createComponentType(); + + /** + * Create a new composite. + * + * @return a new composite + */ + Composite createComposite(); + + /** + * Create a new composite reference. + * + * @return a new composite reference + */ + CompositeReference createCompositeReference(); + + /** + * Create a new composite service. + * + * @return a new composite service + */ + CompositeService createCompositeService(); + + /** + * Create a new constraining type. + * + * @return a new constraining type + */ + ConstrainingType createConstrainingType(); + + /** + * Create a new property. + * + * @return a new property + */ + Property createProperty(); + + /** + * Create a new reference. + * + * @return a new reference + */ + Reference createReference(); + + /** + * Create a new service. + * + * @return a new service + */ + Service createService(); + + /** + * Create a new wire. + * + * @return a new wire + */ + Wire createWire(); + + /** + * Create a new configured operation. + * + * @return a new ConfiguredOperation + */ + ConfiguredOperation createConfiguredOperation(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Base.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Base.java new file mode 100644 index 0000000000..dba3e9f1ae --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Base.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.assembly; + + +/** + * Base interface for all assembly model objects. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public interface Base { + + /** + * Returns true if the model element is unresolved. + * + * @return true if the model element is unresolved. + */ + boolean isUnresolved(); + + /** + * Sets whether the model element is unresolved. + * + * @param unresolved whether the model element is unresolved + */ + void setUnresolved(boolean unresolved); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Binding.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Binding.java new file mode 100644 index 0000000000..028a10c995 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Binding.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.assembly; + + +/** + * Represents a binding. + * + * @version $Rev: 639224 $ $Date: 2008-03-20 02:37:04 -0700 (Thu, 20 Mar 2008) $ + */ +public interface Binding extends Base, Cloneable { + + /** + * Returns the binding URI. + * + * @return the binding URI + */ + String getURI(); + + /** + * Sets the binding URI. + * + * @param uri the binding URI + */ + void setURI(String uri); + + /** + * Returns the binding name. + * + * @return the binding name + */ + String getName(); + + /** + * Sets the binding name. + * + * @param name the binding name + */ + void setName(String name); + + /** + * Clone the binding + * + * @return + */ + Object clone() throws CloneNotSupportedException; +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Callback.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Callback.java new file mode 100644 index 0000000000..c8a36cc555 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Callback.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.assembly; + +import java.util.List; + +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents a callback object describing the bindings to use for callbacks. + * + * @version $Rev: 605979 $ $Date: 2007-12-20 09:01:57 -0800 (Thu, 20 Dec 2007) $ + */ +public interface Callback extends Base, Extensible, IntentAttachPoint, PolicySetAttachPoint, OperationsConfigurator { + + /** + * Returns the bindings supported for callbacks. + * + * @return the bindings supported for callbacks + */ + List getBindings(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Component.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Component.java new file mode 100644 index 0000000000..132569ded3 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Component.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents a component. A component is a configured instance of an + * implementation. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public interface Component extends Base, Extensible, PolicySetAttachPoint, Cloneable { + + /** + * Returns the URI of the component. + * + * @return the URI of the component + */ + String getURI(); + + /** + * Sets the URI of the component. + * + * @param uri the URI of the component + */ + void setURI(String uri); + + /** + * Returns the name of the component. + * + * @return the name of the component + */ + String getName(); + + /** + * Sets the name of the component. + * + * @param name the name of the component + */ + void setName(String name); + + /** + * Returns the component implementation. + * + * @return the component implementation + */ + Implementation getImplementation(); + + /** + * Sets the component implementation + * + * @param implementation the component implementation + */ + void setImplementation(Implementation implementation); + + /** + * Returns a list of references used by the component. + * + * @return a list of references used by the component + */ + List getReferences(); + + /** + * Returns a list of services exposed by the component. + * + * @return a list of services exposed by the component + */ + List getServices(); + + /** + * Returns a list of properties for the component. + * + * @return a list of properties + */ + List getProperties(); + + /** + * Returns a constraining type defining the shape of the component. + * + * @return a constraining type + */ + ConstrainingType getConstrainingType(); + + /** + * Sets a constraining type defining the shape of the component. + * + * @param constrainingType the constraining type + */ + void setConstrainingType(ConstrainingType constrainingType); + + /** + * Return the Boolean value of autowire + * @return null/TRUE/FALSE + */ + Boolean getAutowire(); + + /** + * Sets whether component references should be autowired. + * + * @param autowire whether component references should be autowired + */ + void setAutowire(Boolean autowire); + + + /** + * Returns a clone of the component. + * + * @return a clone of the component + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentProperty.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentProperty.java new file mode 100644 index 0000000000..998540612b --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentProperty.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.assembly; + +import javax.xml.xpath.XPathExpression; + +/** + * Represents a configured property of a component. + * + * @version $Rev: 639224 $ $Date: 2008-03-20 02:37:04 -0700 (Thu, 20 Mar 2008) $ + */ +public interface ComponentProperty extends Property { + + /** + * Returns the property defined by the component implementation. + * + * @return the property defined by the component implementation + */ + Property getProperty(); + + /** + * Sets the property type that defines this property. + * + * @param type the property that defines this property + */ + void setProperty(Property property); + + /** + * Returns an XPath expression referencing a property of the enclosing + * composite. + * + * @return an XPath expression referencing a property of the enclosing + * composite + */ + String getSource(); + + /** + * Sets an XPath expression referencing a property of the enclosing + * composite. + * + * @param source an XPath expression referencing a property of the enclosing + * composite + */ + void setSource(String source); + + /** + * Get the XPath expression for the source attribute + * @return the XPath expression for the source attribute + */ + XPathExpression getSourceXPathExpression(); + + /** + * Set the XPath expression for the source attribute + * @param sourceXPathExpression the XPath expression for the source attribute + */ + void setSourceXPathExpression(XPathExpression sourceXPathExpression); + + /** + * Returns a URI to a file containing the property value. + * + * @return a URI to a file containing the property value + */ + String getFile(); + + /** + * Sets a URI to a file containing the property value. + * + * @param file a URI to a file containing the property value + */ + void setFile(String file); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentReference.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentReference.java new file mode 100644 index 0000000000..5ce75aa7b4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentReference.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.assembly; + + + +/** + * An instance of a reference associated with a particular component. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public interface ComponentReference extends Reference { + + /** + * Returns the reference defined by the implementation for this reference. + * + * @return the implementation reference + */ + Reference getReference(); + + /** + * Sets the reference defined by the implementation for this reference. + * + * @param reference the implementation reference + */ + void setReference(Reference reference); + + /** + * Return the Boolean value of autowire + * @return null/TRUE/FALSE + */ + Boolean getAutowire(); + + /** + * Sets whether component references should be autowired. + * + * @param autowire whether component references should be autowired + */ + void setAutowire(Boolean autowire); + + + /** + * Returns the callback service created internally as a target endpoint + * for callbacks to this reference. + * + * @return the callback service + */ + ComponentService getCallbackService(); + + /** + * Sets the callback service created internally as a target endpoint + * for callbacks to this reference. + * + * @param callbackService the callback service + */ + void setCallbackService(ComponentService callbackService); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentService.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentService.java new file mode 100644 index 0000000000..74110329f5 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentService.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + + +/** + * An addressable instance of a service associated with a particular component. + * + * @version $Rev: 564107 $ $Date: 2007-08-08 23:05:29 -0700 (Wed, 08 Aug 2007) $ + */ +public interface ComponentService extends Service { + + /** + * Returns the service defined by the implementation for this service. + * + * @return + */ + Service getService(); + + /** + * Sets the service defined by the implementation for this service. + * + * @param service + */ + void setService(Service service); + + /** + * Returns the callback reference created internally as a source endpoint + * for callbacks from this service. + * + * @return the callback reference + */ + ComponentReference getCallbackReference(); + + /** + * Sets the callback reference created internally as a source endpoint + * for callbacks from this service. + * + * @param callbackReference the callback reference + */ + void setCallbackReference(ComponentReference callbackReference); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentType.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentType.java new file mode 100644 index 0000000000..c4ad4fa0cb --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ComponentType.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +/** + * Describes an implementation and represents its configurable aspects. + * + * @version $Rev: 567222 $ $Date: 2007-08-17 20:47:14 -0700 (Fri, 17 Aug 2007) $ + */ +public interface ComponentType extends Base { + + /** + * Returns the URI of this component type. + * @return the URI of the component type + */ + String getURI(); + + /** + * Sets the URI of this component type. + * @param uri the URI of the component type + */ + void setURI(String uri); + + /** + * Returns a list of services that are offered. + * + * @return a list of services that are offered + */ + List getServices(); + + /** + * Returns the list of reference types that are used. + * + * @return the list of reference types that are used + */ + List getReferences(); + + /** + * Returns the list of properties that can be set. + * + * @return the list of properties that can be set + */ + List getProperties(); + + /** + * Returns a constraining type defining the shape of the implementation. + * + * @return a constraining type + */ + ConstrainingType getConstrainingType(); + + /** + * Sets a constraining type defining the shape of the implementation. + * + * @param constrainingType the constraining type to set + */ + void setConstrainingType(ConstrainingType constrainingType); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Composite.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Composite.java new file mode 100644 index 0000000000..bd8f97910e --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Composite.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + + +/** + * Represents a composite. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public interface Composite extends Implementation, Extensible, Cloneable, PolicySetAttachPoint { + + /** + * Returns the name of the composite. + * + * @return the name of the composite + */ + QName getName(); + + /** + * Sets the name of the composite. + * + * @param name the name of the composite + */ + void setName(QName name); + + /** + * Returns a list of composites included in this composite. + * + * @return a list of composites included in this composite. + */ + List getIncludes(); + + /** + * Returns a list of components contained in this composite. + * + * @return a list of components contained in this composite + */ + List getComponents(); + + /** + * Returns a list of wires contained in this composite. + * + * @return a list of wires contained in this composite + */ + List getWires(); + + /** + * Returns true if all the components within the composite must run in the + * same process. + * + * @return true if all the components within the composite must run in the + * same process + */ + boolean isLocal(); + + /** + * Sets whether all the components within the composite must run in the same + * process. + * + * @param local whether all the components within the composite must run in + * the same process + */ + void setLocal(boolean local); + + /** + * Return the Boolean value of autowire + * @return null/TRUE/FALSE + */ + Boolean getAutowire(); + + /** + * Sets whether component references should be autowired. + * + * @param autowire whether component references should be autowired + */ + void setAutowire(Boolean autowire); + + + /** + * Returns a clone of the component type. + * + * @return a clone of the component type + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeReference.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeReference.java new file mode 100644 index 0000000000..8b55127870 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeReference.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +/** + * Represents composite reference. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public interface CompositeReference extends Reference { + + /** + * Returns the promoted composite references. + * + * @return the promoted composite references + */ + List getPromotedReferences(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeService.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeService.java new file mode 100644 index 0000000000..2f7b2d0da4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/CompositeService.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +/** + * Represents a composite service. + * + * @version $Rev: 566036 $ $Date: 2007-08-14 23:16:47 -0700 (Tue, 14 Aug 2007) $ + */ +public interface CompositeService extends Service { + + /** + * Returns the promoted component. + * + * @return the promoted component. + */ + Component getPromotedComponent(); + + /** + * Sets the promoted component + * + * @param promotedComponent the promoted component. + */ + void setPromotedComponent(Component promotedComponent); + + /** + * Returns the promoted component service . + * + * @return the promoted component service. + */ + ComponentService getPromotedService(); + + /** + * Sets the promoted component service + * + * @param promotedService the promoted component service. + */ + void setPromotedService(ComponentService promotedService); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConfiguredOperation.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConfiguredOperation.java new file mode 100644 index 0000000000..a412bcee24 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConfiguredOperation.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents an Operation. Typically Operation elements are used when there is a + * need to apply certain facets such as intents and policysets only to a specific + * operation provided by a service or reference. + */ +public interface ConfiguredOperation extends Base, PolicySetAttachPoint { + /** + * Returns the name of the operation. + * + * @return the name of the operation + */ + String getName(); + + /** + * Sets the name of the operation. + * + * @param name the name of the operation + */ + void setName(String name); + + /** + * Returns the name of the service or reference to which this operation belongs. + * This method is particularly useful when operation elements are specified under implementation + * elements and it is necessary to identify which of the various services provided by the + * implementation is referred to by the operation element in question + * + * @return the name of the contract to which this operation belongs + */ + String getContractName(); + + /** + * Sets the name of the service or reference to which this operation belongs. + * + * @param the name of the contract to which this operation belongs + */ + void setContractName(String contractName); +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConstrainingType.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConstrainingType.java new file mode 100644 index 0000000000..1bd27d07b3 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/ConstrainingType.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.policy.IntentAttachPoint; + +/** + * A constrainingType provides the "shape" for a component and its + * implementation. Any component configuration that points to a constrainingType + * is constrained by this shape. The constrainingType specifies the services, + * references and properties that must be implemented. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public interface ConstrainingType extends Base, Extensible, IntentAttachPoint { + + /** + * Returns the name of the constrainingType. + * + * @return the name of the constrainingType + */ + QName getName(); + + /** + * Sets the name of the constrainingType. + * + * @param name the name of the constrainingType + */ + void setName(QName name); + + /** + * Returns a list of services that are offered. + * + * @return a list of services that are offered + */ + List getServices(); + + /** + * Returns the list of references that are used. + * + * @return the list of references that are used + */ + List getReferences(); + + /** + * Returns the list of properties that can be set. + * + * @return the list of properties that can be set + */ + List getProperties(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Contract.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Contract.java new file mode 100644 index 0000000000..a717715554 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Contract.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents a contract. A contract can be either a service or a reference. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public interface Contract extends AbstractContract, PolicySetAttachPoint, Cloneable { + + /** + * Returns the bindings supported by this contract. + * + * @return the bindings supported by this contract + */ + List getBindings(); + + /** + * Returns a binding of the specified type or null if there is no such + * binding configured on this contract. + * + * @param the binding type + * @param bindingClass the binding type class + * @return the binding or null if there is no binding of the specified type + */ + B getBinding(Class bindingClass); + + /** + * Returns a callback binding of the specified type or null if there is no such + * callback binding configured on this contract. + * + * @param the callback binding type + * @param bindingClass the callback binding type class + * @return the callback binding or null if there is no callback binding of the specified type + */ + B getCallbackBinding(Class bindingClass); + + /** + * Returns a callback definition of the bindings to use for callbacks. + * + * @return a definition of the bindings to use for callbacks + */ + Callback getCallback(); + + /** + * Sets a callback definition of the bindings to use for callbacks + * + * @param callback a definition of the bindings to use for callbacks + */ + void setCallback(Callback callback); + + /** + * Returns a clone of the contract. + * + * @return a clone of the reference + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/DefaultAssemblyFactory.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/DefaultAssemblyFactory.java new file mode 100644 index 0000000000..1205c4ce6c --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/DefaultAssemblyFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.assembly.impl.AssemblyFactoryImpl; + +/** + * A factory for the assembly model. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public class DefaultAssemblyFactory extends AssemblyFactoryImpl implements AssemblyFactory { + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Extensible.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Extensible.java new file mode 100644 index 0000000000..ce998c0662 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Extensible.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +/** + * Base interface for extensible assembly model objects. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public interface Extensible { + + /** + * Returns a list of extension objects contained in this model object. + * + * @return a list of extension objects container in this model object + */ + List getExtensions(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Implementation.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Implementation.java new file mode 100644 index 0000000000..ad47c4c5aa --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Implementation.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly; + +/** + * Represents a component implementation. + * + * @version $Rev: 596604 $ $Date: 2007-11-20 02:35:30 -0800 (Tue, 20 Nov 2007) $ + */ +public interface Implementation extends ComponentType { +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Multiplicity.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Multiplicity.java new file mode 100644 index 0000000000..a93c3c5ee3 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Multiplicity.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +/** + * Enumeration for multiplicity. Defines the number of wires that can connect a + * reference to target services. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public enum Multiplicity { + + /** + * Zero or one wire can have the reference as a source. + */ + ZERO_ONE, + + /** + * The default setting, one wire can have the reference as a source. + */ + ONE_ONE, + + /** + * Zero or more wires can have the reference as a source. + */ + ZERO_N, + + /** + * One or more wires can have the reference as a source. + */ + ONE_N + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OperationsConfigurator.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OperationsConfigurator.java new file mode 100644 index 0000000000..2ca8589b1a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OperationsConfigurator.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.ConfiguredOperation; + +/** + * Interface to be implemented by SCA artifacts that support configuration of 'operation' child + * elements for policies etc. + */ + +public interface OperationsConfigurator { + List getConfiguredOperations(); +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OptimizableBinding.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OptimizableBinding.java new file mode 100644 index 0000000000..1eb2188568 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/OptimizableBinding.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.assembly; + +/** + * Represent a reference binding that supports optimized SCA local wiring between component + * references and services + * + * @version $Rev: 575759 $ $Date: 2007-09-14 10:09:31 -0700 (Fri, 14 Sep 2007) $ + * + */ +public interface OptimizableBinding extends Binding, Cloneable { + + /** + * @param component + */ + void setTargetComponent(Component component); + + /** + * @param service + */ + void setTargetComponentService(ComponentService service); + + /** + * @param binding + */ + void setTargetBinding(Binding binding); + + /** + * @return + */ + Binding getTargetBinding(); + + /** + * @return + */ + Component getTargetComponent(); + + /** + * @return + */ + ComponentService getTargetComponentService(); + + /** + * Clone the binding + * @return + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Property.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Property.java new file mode 100644 index 0000000000..8828e36970 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Property.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * A property allows for the configuration of an implementation with externally + * set data values. An implementation can have zero or more properties. Each + * property has a data type, which may be either simple or complex. An + * implementation may also define a default value for a property. + * + * @version $Rev: 560488 $ $Date: 2007-07-27 21:18:42 -0700 (Fri, 27 Jul 2007) $ + */ +public interface Property extends AbstractProperty, PolicySetAttachPoint, Cloneable { + + /** + * Returns a clone of the property. + * + * @return a clone of the property + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Reference.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Reference.java new file mode 100644 index 0000000000..874164e78a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Reference.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import java.util.List; + +/** + * Represents a reference. References within an implementation represent links + * to services that the implementation uses that must be provided by other + * components. + * + * @version $Rev: 560488 $ $Date: 2007-07-27 21:18:42 -0700 (Fri, 27 Jul 2007) $ + */ +public interface Reference extends AbstractReference, Contract { + + /** + * Returns a boolean value, "false" by default, which indicates that the + * implementation wires this reference dynamically. + * + * @return true if the implementation wires this reference dynamically + */ + boolean isWiredByImpl(); + + /** + * Sets a boolean value, "false" by default, which indicates that the + * implementation wires this reference dynamically. + * + * @param wiredByImpl whether the implementation wires this reference + * dynamically + */ + void setWiredByImpl(boolean wiredByImpl); + + /** + * Returns the targets of this reference. + * + * @return the targets of this reference. + */ + List getTargets(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABinding.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABinding.java new file mode 100644 index 0000000000..ece8eeb028 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABinding.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly; + +/** + * Represents an SCA binding. + * + * @version $Rev: 566036 $ $Date: 2007-08-14 23:16:47 -0700 (Tue, 14 Aug 2007) $ + */ +public interface SCABinding extends Binding { +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABindingFactory.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABindingFactory.java new file mode 100644 index 0000000000..881d7df5e4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/SCABindingFactory.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.assembly; + + +/** + * A factory for the SCA binding model + * + * @version $Rev: 538819 $ $Date: 2007-05-16 23:54:50 -0700 (Wed, 16 May 2007) $ + */ +public interface SCABindingFactory { + + /** + * Create a new SCA binding. + * + * @return a new SCA binding + */ + SCABinding createSCABinding(); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Service.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Service.java new file mode 100644 index 0000000000..c63bee0303 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Service.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +/** + * Represents a service. Services are used to publish services provided by + * implementations, so that they are addressable by other components. + * + * @version $Rev: 560488 $ $Date: 2007-07-27 21:18:42 -0700 (Fri, 27 Jul 2007) $ + */ +public interface Service extends AbstractService, Contract { + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Wire.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Wire.java new file mode 100644 index 0000000000..bd457b3c34 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/Wire.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.assembly; + +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents a wire. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public interface Wire extends Base, Extensible, IntentAttachPoint, PolicySetAttachPoint, Cloneable { + + /** + * Returns the source of the wire. + * + * @return the source of the wire + */ + ComponentReference getSource(); + + /** + * Sets the source of the wire. + * + * @param source the source of the wire + */ + void setSource(ComponentReference source); + + /** + * Returns the target of the wire. + * + * @return the target of the wire + */ + ComponentService getTarget(); + + /** + * Sets the target of the wire. + * + * @param target the target of the wire + */ + void setTarget(ComponentService target); + + /** + * Returns a clone of the wire. + * + * @return a clone of the wire + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java new file mode 100644 index 0000000000..e0ac9ada03 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/ComponentPreProcessor.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder; + +import org.apache.tuscany.sca.assembly.Component; + +public interface ComponentPreProcessor { + + void preProcess(Component component); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.java new file mode 100644 index 0000000000..050a7e5cb5 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilder.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.assembly.builder; + +import org.apache.tuscany.sca.assembly.Composite; + +/** + * A builder that handles the configuration of the components inside a + * composite and the wiring of component references to component services. + * + * @version $Rev: 563358 $ $Date: 2007-08-06 17:26:27 -0700 (Mon, 06 Aug 2007) $ + */ +public interface CompositeBuilder { + + /** + * Build, configure and wire a composite. + * + * @param composite + * @throws CompositeBuilderException + */ + void build(Composite composite) throws CompositeBuilderException; + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.java new file mode 100644 index 0000000000..c2c91f715e --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderException.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.assembly.builder; + +/** + * Reports a composite builder exception. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public class CompositeBuilderException extends Exception { + private static final long serialVersionUID = -8916323176803443856L; + + public CompositeBuilderException() { + } + + public CompositeBuilderException(String message) { + super(message); + } + + public CompositeBuilderException(Throwable cause) { + super(cause); + } + + public CompositeBuilderException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderMonitor.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderMonitor.java new file mode 100644 index 0000000000..5630d19366 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/CompositeBuilderMonitor.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.assembly.builder; + +/** + * A monitor for the composite builder. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public interface CompositeBuilderMonitor { + + /** + * Reports a build problem. + * + * @param problem + */ + void problem(Problem problem); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.java new file mode 100644 index 0000000000..88468938fd --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/DomainBuilder.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.assembly.builder; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Service; + +/** + * A builder that handles the configuration of the components inside a + * composite and the wiring of component references to component services. + * + * @version $Rev: 563358 $ $Date: 2007-08-07 01:26:27 +0100 (Tue, 07 Aug 2007) $ + */ +public interface DomainBuilder { + + /** + * Wire up the references and service in a domain returning a list + * of the composites that have changed + * + * @param domainLevelCompsite + * @return a list of change composites + * @throws CompositeBuilderException + */ + public List wireDomain(Composite domainLevelComposite); + + /** + * Locates the referenced service and updates the URI on the identified binding + * + * @param domainLevelComposite + * @param referenceName + * @param bindingClassName + * @param URI + */ + public void updateDomainLevelServiceURI(Composite domainLevelComposite, String referenceName, String bindingClassName, String URI); + + /** + * Get the component name out of the reference name that might look like Component/Service + * + * @param referenceName + * @return + */ + public String getComponentNameFromReference(String referenceName); + + /** + * Get the service name out of the reference name that might look like Component/Service + * + * @param referenceName + * @return + */ + public String getServiceNameFromReference(String referenceName); + + /** + * Find the service object given a reference name + * + * @param composite + * @param referenceName + * @return + */ + public Service findServiceForReference(Composite composite, String referenceName); + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/Problem.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/Problem.java new file mode 100644 index 0000000000..70ec19288a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/Problem.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.assembly.builder; + + +/** + * Reports a composite assembly problem. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public interface Problem { + + public enum Severity { + INFO, + WARNING, + ERROR + } + + Severity getSeverity(); + + String getMessage(); + + Object getModel(); + + Object getResource(); + + Exception getCause(); +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingPolicyComputer.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingPolicyComputer.java new file mode 100644 index 0000000000..ec25c8e2a7 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingPolicyComputer.java @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.util.PolicyComputationUtils; +import org.apache.tuscany.sca.policy.util.PolicyValidationException; + +/** + * Policy computation methods pertaining to computing Binding policies + */ +public class BindingPolicyComputer extends PolicyComputer { + + public BindingPolicyComputer() { + super(); + } + + public void computeBindingIntentsAndPolicySets(Contract contract) throws PolicyValidationException { + for (Binding binding : contract.getBindings()) { + if (binding instanceof PolicySetAttachPoint) { + computeIntents((IntentAttachPoint)binding, contract.getRequiredIntents()); + + aggregateAndPruneApplicablePolicySets(contract.getApplicablePolicySets(), + ((PolicySetAttachPoint)binding).getApplicablePolicySets()); + + computePolicySets((PolicySetAttachPoint)binding, contract.getPolicySets()); + + if ( binding instanceof OperationsConfigurator && + contract instanceof OperationsConfigurator ) { + //add or merge service operations to the binding + addInheritedOpConfOnBindings((OperationsConfigurator)contract, + (OperationsConfigurator)binding, + (PolicySetAttachPoint)binding); + + computeIntentsForOperations((IntentAttachPoint)binding); + computePolicySetsForOperations(contract.getApplicablePolicySets(), + (PolicySetAttachPoint)binding); + } + } + } + + if ( contract.getCallback() != null ) { + for (Binding binding : contract.getCallback().getBindings()) { + if (binding instanceof PolicySetAttachPoint) { + computeIntents((IntentAttachPoint)binding, contract.getCallback().getRequiredIntents()); + + aggregateAndPruneApplicablePolicySets(contract.getApplicablePolicySets(), + ((PolicySetAttachPoint)binding).getApplicablePolicySets()); + + computePolicySets((PolicySetAttachPoint)binding, contract.getCallback().getPolicySets()); + } + } + } + } + + + private void computeIntents(IntentAttachPoint policiedBinding, List inheritedIntents) + throws PolicyValidationException { + //since the parent component could also contain intents that apply to implementation + //and binding elements within, we filter out only those that apply to this binding type + List prunedIntents = computeInheritableIntents(policiedBinding.getType(), + inheritedIntents); + policiedBinding.getRequiredIntents().addAll(prunedIntents); + + normalizeIntents(policiedBinding); + } + + + private void computePolicySets(PolicySetAttachPoint policiedBinding, + List inheritedPolicySets) throws PolicyValidationException { + + List prunedPolicySets = computeInheritablePolicySets(inheritedPolicySets, + policiedBinding.getApplicablePolicySets()); + policiedBinding.getPolicySets().addAll(prunedPolicySets); + normalizePolicySets(policiedBinding); + } + + public void determineApplicableBindingPolicySets(Contract source, Contract target) throws PolicyComputationException { + List intentsCopy = null; + for (Binding aBinding : source.getBindings()) { + if (aBinding instanceof PolicySetAttachPoint) { + PolicySetAttachPoint policiedBinding = (PolicySetAttachPoint)aBinding; + IntentAttachPointType bindingType = policiedBinding.getType(); + + + intentsCopy = new ArrayList(policiedBinding.getRequiredIntents()); + // add the target component's intents to the reference binding + if (target != null) { + for (Intent intent : target.getRequiredIntents()) { + if (!policiedBinding.getRequiredIntents().contains(intent)) { + for (QName constrained : intent.getConstrains()) { + if (bindingType != null && bindingType.getName().getNamespaceURI() + .equals(constrained.getNamespaceURI()) + && bindingType.getName().getLocalPart().startsWith(constrained + .getLocalPart())) { + policiedBinding.getRequiredIntents().add(intent); + break; + } + } + } + } + } + + //trim intents specified in operations. First check for policysets specified on the operation + //and then in the parent implementation + if ( aBinding instanceof OperationsConfigurator ) { + OperationsConfigurator opConfigurator = (OperationsConfigurator)aBinding; + + for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) { + List opsIntentsCopy = new ArrayList(confOp.getRequiredIntents()); + + trimInherentlyProvidedIntents(policiedBinding.getType(), + confOp.getRequiredIntents()); + trimProvidedIntents(confOp.getRequiredIntents(), confOp.getPolicySets()); + trimProvidedIntents(confOp.getRequiredIntents(), policiedBinding.getPolicySets()); + + determineApplicableDomainPolicySets(policiedBinding.getApplicablePolicySets(), + confOp, + policiedBinding.getType()); + + if (confOp.getRequiredIntents().size() > 0) { + new PolicyComputationException("The following are unfulfilled intents for operations configured in " + + "binding - " + aBinding.getName() + "\nUnfulfilled Intents = " + + confOp.getRequiredIntents()); + } + + //the intents list could have been trimmed when matching for policysets + //since the bindings may need the original set of intents we copy that back + confOp.getRequiredIntents().clear(); + confOp.getRequiredIntents().addAll(opsIntentsCopy); + + } + } + + trimInherentlyProvidedIntents(policiedBinding.getType(), + policiedBinding.getRequiredIntents()); + trimProvidedIntents(policiedBinding.getRequiredIntents(), policiedBinding + .getPolicySets()); + + // determine additional policysets that match remaining intents + // TODO: resolved to domain policy registry and attach suitable + // policy sets to the binding + // for now using the SCA Definitions instead of registry + // if there are intents that are not provided by any policy set + // throw a warning + determineApplicableDomainPolicySets(source, policiedBinding); + + //the intents list could have been trimmed when matching for policysets + //since the bindings may need the original set of intents we copy that back + policiedBinding.getRequiredIntents().clear(); + policiedBinding.getRequiredIntents().addAll(intentsCopy); + + } + } + } + + private void determineApplicableDomainPolicySets(Contract contract, + PolicySetAttachPoint policiedBinding) + throws PolicyComputationException { + //if ( domainPolicySets != null) { + determineApplicableDomainPolicySets(policiedBinding.getApplicablePolicySets(), + policiedBinding, + policiedBinding.getType()); + + if ( policiedBinding.getRequiredIntents().size() > 0 ) { + if ( contract instanceof Service ) { + throw new PolicyComputationException("The following are unfulfilled intents for " + + "binding in service - " + contract.getName() + "\nUnfulfilled Intents = " + + policiedBinding.getRequiredIntents()); + } else { + throw new PolicyComputationException("The are unfulfilled intents for " + + "binding in reference - " + contract.getName() + "\nUnfulfilled Intents = " + + policiedBinding.getRequiredIntents()); + } + } + //} + } + + private void addInheritedOpConfOnBindings(OperationsConfigurator source, + OperationsConfigurator target, + PolicySetAttachPoint attachPoint) throws PolicyValidationException { + boolean found = false; + + List additionalOperations = new ArrayList(); + for ( ConfiguredOperation sourceConfOp : source.getConfiguredOperations() ) { + for ( ConfiguredOperation targetConfOp : target.getConfiguredOperations() ) { + if ( sourceConfOp.getName().equals(targetConfOp.getName())) { + List prunedIntents = computeInheritableIntents(attachPoint.getType(), + sourceConfOp.getRequiredIntents()); + PolicyComputationUtils.addInheritedIntents(prunedIntents, + targetConfOp.getRequiredIntents()); + + List prunedPolicySets = computeInheritablePolicySets(sourceConfOp.getPolicySets(), + attachPoint.getApplicablePolicySets()); + PolicyComputationUtils.addInheritedPolicySets(prunedPolicySets, targetConfOp.getPolicySets(), true); + found = true; + break; + } + } + + if ( !found ) { + additionalOperations.add(sourceConfOp); + } + } + + if ( !additionalOperations.isEmpty() ) { + target.getConfiguredOperations().addAll(additionalOperations); + } + } + + /*private void addInheritedOpConfOnBindings(Contract contract) { + for ( Binding binding : contract.getBindings() ) { + if ( binding instanceof OperationsConfigurator ) { + addInheritedOperationConfigurations(contract, (OperationsConfigurator)binding); + } + } + }*/ + + private void aggregateAndPruneApplicablePolicySets(List source, List target) { + target.addAll(source); + //strip duplicates + Hashtable policySetTable = new Hashtable(); + for ( PolicySet policySet : target ) { + policySetTable.put(policySet.getName(), policySet); + } + + target.clear(); + target.addAll(policySetTable.values()); + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingUtil.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingUtil.java new file mode 100644 index 0000000000..791d131871 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/BindingUtil.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.builder.impl; + +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.OptimizableBinding; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * This class encapsulates utility methods to deal with binding definitions + */ +class BindingUtil { + private static boolean hasCompatiblePolicySets(Binding refBinding, Binding svcBinding) { + boolean isCompatible = true;; + if ( refBinding instanceof PolicySetAttachPoint && svcBinding instanceof PolicySetAttachPoint ) { + //TODO : need to add more compatibility checks at the policy attachment levels + for ( PolicySet svcPolicySet : ((PolicySetAttachPoint)svcBinding).getPolicySets() ) { + isCompatible = false; + for ( PolicySet refPolicySet : ((PolicySetAttachPoint)refBinding).getPolicySets() ) { + if ( svcPolicySet.equals(refPolicySet) ) { + isCompatible = true; + break; + } + } + //if there exists no matching policy set in the reference binding + if ( !isCompatible ) { + return isCompatible; + } + } + } + return isCompatible; + } + + + public static Binding matchBinding(Component component, ComponentService service, List source, List target) { + List matched = new ArrayList(); + // Find the corresponding bindings from the service side + for (Binding binding : source) { + for (Binding serviceBinding : target) { + if (binding.getClass() == serviceBinding.getClass() && + hasCompatiblePolicySets(binding, serviceBinding)) { + + try { + Binding cloned = (Binding)binding.clone(); + + //Customise the binding name to make it unique + // regardless of how many bindings or targets there are + if ( component != null){ + cloned.setName(binding.getName() + "#" + component.getName() + "/" + serviceBinding.getName()); + } else { + cloned.setName(binding.getName() + "#" + serviceBinding.getName()); + } + + // Set the binding URI to the URI of the target service + // that has been matched + if (binding.getURI() == null) { + cloned.setURI(serviceBinding.getURI()); + } + + if (binding instanceof OptimizableBinding) { + OptimizableBinding endpoint = ((OptimizableBinding)cloned); + endpoint.setTargetComponent(component); + endpoint.setTargetComponentService(service); + endpoint.setTargetBinding(serviceBinding); + } + + matched.add(cloned); + break; + } catch (Exception ex) { + // do nothing + } + } + } + } + if (matched.isEmpty()) { + // No matching binding + return null; + } else { + for (Binding binding : matched) { + // If binding.sca is present, use it + if (SCABinding.class.isInstance(binding)) { + return binding; + } + } + // Use the first one + return matched.get(0); + } + } + + /** + * Choose a binding for the reference based on the bindings available on the + * service + * + * @param reference The component reference + * @param service The component service + * @return Resolved binding + */ + static Binding resolveBindings(ComponentReference reference, Component component, ComponentService service) { + List source = reference.getBindings(); + List target = service.getBindings(); + + return matchBinding(component, service, source, target); + + } + + + /** + * @param reference + * @param service + * @return + */ + static Binding resolveCallbackBindings(ComponentReference reference, Component component, ComponentService service) { + List source = reference.getCallback().getBindings(); + List target = service.getCallback().getBindings(); + + return matchBinding(component, service, source, target); + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.java new file mode 100644 index 0000000000..caa212ccdf --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderImpl.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.assembly.builder.impl; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; +import org.apache.tuscany.sca.assembly.builder.Problem; +import org.apache.tuscany.sca.assembly.builder.Problem.Severity; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; + +/** + * A builder that handles the configuration of the components inside a composite + * and the wiring of component references to component services. + * + * @version $Rev: 643489 $ $Date: 2008-04-01 10:06:42 -0800 (Tue, 01 Apr 2008) $ + */ +public class CompositeBuilderImpl implements CompositeBuilder { + private final static Logger logger = Logger.getLogger(CompositeBuilderImpl.class.getName()); + private CompositeIncludeBuilderImpl includeBuilder; + private CompositeWireBuilderImpl wireBuilder; + private CompositeCloneBuilderImpl cloneBuilder; + private CompositeConfigurationBuilderImpl configurationBuilder; + + /** + * Constructs a new composite util. + * + * @param assemblyFactory + * @param interfaceContractMapper + */ + public CompositeBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper, + CompositeBuilderMonitor monitor) { + + if (monitor == null) { + // Create a default monitor that logs using the JDK logger. + monitor = new CompositeBuilderMonitor() { + public void problem(Problem problem) { + if (problem.getSeverity() == Severity.INFO) { + logger.info(problem.toString()); + } else if (problem.getSeverity() == Severity.WARNING) { + logger.warning(problem.toString()); + } else if (problem.getSeverity() == Severity.ERROR) { + if (problem.getCause() != null) { + logger.log(Level.SEVERE, problem.toString(), problem.getCause()); + } else { + logger.severe(problem.toString()); + } + } + } + }; + } + + includeBuilder = new CompositeIncludeBuilderImpl(monitor); + wireBuilder = new CompositeWireBuilderImpl(assemblyFactory, interfaceContractMapper, monitor); + cloneBuilder = new CompositeCloneBuilderImpl(monitor); + configurationBuilder = new CompositeConfigurationBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, monitor); + + } + + public CompositeBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper, + CompositeBuilderMonitor monitor, + SCADefinitions scaDefns) { + this(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, monitor); + configurationBuilder.setScaDefinitions(scaDefns); + } + + public void build(Composite composite) throws CompositeBuilderException { + + // Collect and fuse includes + includeBuilder.fuseIncludes(composite); + + // Expand nested composites + cloneBuilder.expandCompositeImplementations(composite); + + // Configure all components + configurationBuilder.configureComponents(composite); + + // Wire the composite + wireBuilder.wireComposite(composite); + + // Activate composite services + configurationBuilder.activateCompositeServices(composite); + + // Wire composite references + wireBuilder.wireCompositeReferences(composite); + + // Fuse nested composites + //cloneBuilder.fuseCompositeImplementations(composite); + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java new file mode 100644 index 0000000000..142bed9d63 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeCloneBuilderImpl.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; + +public class CompositeCloneBuilderImpl { + + public CompositeCloneBuilderImpl(CompositeBuilderMonitor monitor) { + } + + /** + * Expand composite component implementations. + * + * @param composite + * @param problems + */ + public void expandCompositeImplementations(Composite composite) { + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + Composite compositeImplementation = (Composite)implementation; + Composite clone; + try { + clone = (Composite)compositeImplementation.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + component.setImplementation(clone); + expandCompositeImplementations(clone); + } + } + } + + /** + * Collect all nested composite implementations in a graph of composites. + * + * @param composite + * @param nested + */ + private void collectNestedComposites(Composite composite, List nested) { + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + Composite nestedComposite = (Composite)implementation; + nested.add(nestedComposite); + collectNestedComposites(nestedComposite, nested); + } + } + } + + /** + * Fuse nested composites into a top level composite. + * + * @param composite + */ + public void fuseCompositeImplementations(Composite composite) { + + // First collect all nested composites + List nested = new ArrayList(); + collectNestedComposites(composite, nested); + + // Then add all the non-composite components they contain + for (Composite nestedComposite : nested) { + for (Component component: nestedComposite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (!(implementation instanceof Composite)) { + composite.getComponents().add(component); + } + } + } + + // Clear the initial list of composite components + for (Iterator i = composite.getComponents().iterator(); i.hasNext();) { + Component component = i.next(); + if (component.getImplementation() instanceof Composite) { + i.remove(); + } + } + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeConfigurationBuilderImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeConfigurationBuilderImpl.java new file mode 100644 index 0000000000..9040b8bd99 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeConfigurationBuilderImpl.java @@ -0,0 +1,1417 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +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.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.ComponentPreProcessor; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; +import org.apache.tuscany.sca.assembly.builder.Problem.Severity; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +public class CompositeConfigurationBuilderImpl { + private final static String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0"; + private final static String BINDING_SCA = "binding.sca"; + private final static QName BINDING_SCA_QNAME = new QName(SCA10_NS, BINDING_SCA); + + private AssemblyFactory assemblyFactory; + private SCABindingFactory scaBindingFactory; + private CompositeBuilderMonitor monitor; + private InterfaceContractMapper interfaceContractMapper; + private IntentAttachPointTypeFactory intentAttachPointTypeFactory; + private SCADefinitions scaDefinitions = null; + + public CompositeConfigurationBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper, + CompositeBuilderMonitor monitor) { + this.assemblyFactory = assemblyFactory; + this.scaBindingFactory = scaBindingFactory; + this.intentAttachPointTypeFactory = intentAttachPointTypeFactory; + this.interfaceContractMapper = interfaceContractMapper; + this.monitor = monitor; + } + + /** + * Configure components in the composite. + * + * @param composite + * @param problems + */ + public void configureComponents(Composite composite) throws CompositeBuilderException { + configureComponents(composite, null); + configureSourcedProperties(composite, null); + configureBindingURIs(composite, null, null); + } + + /** + * Configure components in the composite. + * + * @param composite + * @param uri + * @param problems + */ + private void configureComponents(Composite composite, String uri) { + String parentURI = uri; + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + + // Initialize component URI + String componentURI; + if (parentURI == null) { + componentURI = component.getName(); + } else { + componentURI = URI.create(parentURI + '/').resolve(component.getName()).toString(); + } + component.setURI(componentURI); + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // Process nested composite + configureComponents((Composite)implementation, componentURI); + } + } + + // Initialize service bindings + List compositeServices = composite.getServices(); + for (Service service : compositeServices) { + // Set default binding names + + // Create default SCA binding + if (service.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + service.getBindings().add(scaBinding); + } + + // Initialize binding names and URIs + for (Binding binding : service.getBindings()) { + + // Binding name defaults to the service name + if (binding.getName() == null) { + binding.setName(service.getName()); + } + } + + if (service.getCallback() != null) { + for (Binding binding : service.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(service.getName()); + } + } + } + } + + // Initialize reference bindings + for (Reference reference : composite.getReferences()) { + // Create default SCA binding + if (reference.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + reference.getBindings().add(scaBinding); + } + + // Set binding names + for (Binding binding : reference.getBindings()) { + if (binding.getName() == null) { + binding.setName(reference.getName()); + } + } + + if (reference.getCallback() != null) { + for (Binding binding : reference.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(reference.getName()); + } + } + } + } + + // Initialize all component services and references + Map components = new HashMap(); + for (Component component : composite.getComponents()) { + + // Index all components and check for duplicates + if (components.containsKey(component.getName())) { + warning("Duplicate component name: " + composite.getName() + + " : " + + component.getName(), composite); + } else { + components.put(component.getName(), component); + } + + // Propagate the autowire flag from the composite to components + if (component.getAutowire() == null) { + component.setAutowire(composite.getAutowire()); + } + + if (component.getImplementation() instanceof ComponentPreProcessor) { + ((ComponentPreProcessor)component.getImplementation()).preProcess(component); + } + + // Index properties, services and references + Map services = new HashMap(); + Map references = new HashMap(); + Map properties = new HashMap(); + indexImplementationPropertiesServicesAndReferences(component, + services, + references, + properties); + + // Index component services, references and properties + // Also check for duplicates + Map componentServices = + new HashMap(); + Map componentReferences = + new HashMap(); + Map componentProperties = + new HashMap(); + indexComponentPropertiesServicesAndReferences(component, + componentServices, + componentReferences, + componentProperties); + + // Reconcile component services/references/properties and + // implementation services/references and create component + // services/references/properties for the services/references + // declared by the implementation + reconcileServices(component, services, componentServices); + reconcileReferences(component, references, componentReferences); + reconcileProperties(component, properties, componentProperties); + + // Configure or create callback services for component's references + // with callbacks + configureCallbackServices(component, componentServices); + + // Configure or create callback references for component's services + // with callbacks + configureCallbackReferences(component, componentReferences); + + // Create self references to the component's services +// if (!(component.getImplementation() instanceof Composite)) { +// createSelfReferences(component); +// } + + // Initialize service bindings + for (ComponentService componentService : component.getServices()) { + + // Create default SCA binding + if (componentService.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + componentService.getBindings().add(scaBinding); + } + + // Set binding names + for (Binding binding : componentService.getBindings()) { + + // Binding name defaults to the service name + if (binding.getName() == null) { + binding.setName(componentService.getName()); + } + } + if (componentService.getCallback() != null) { + for (Binding binding : componentService.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(componentService.getName()); + } + } + } + } + + // Initialize reference bindings + for (ComponentReference componentReference : component.getReferences()) { + + // Create default SCA binding + if (componentReference.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + componentReference.getBindings().add(scaBinding); + } + + // Set binding names + for (Binding binding : componentReference.getBindings()) { + if (binding.getName() == null) { + binding.setName(componentReference.getName()); + } + } + if (componentReference.getCallback() != null) { + for (Binding binding : componentReference.getCallback().getBindings()) { + if (binding.getName() == null) { + binding.setName(componentReference.getName()); + } + } + } + } + } + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(String message, Object model) { + monitor.problem(new ProblemImpl(Severity.WARNING, message, model)); + } + + /** + * Reconcile component properties and the properties defined by the + * component type. + * + * @param component + * @param properties + * @param componentProperties + * @param problems + */ + private void reconcileProperties(Component component, + Map properties, + Map componentProperties) { + + // Connect component properties to their properties + for (ComponentProperty componentProperty : component.getProperties()) { + Property property = properties.get(componentProperty.getName()); + if (property != null) { + componentProperty.setProperty(property); + } else { + warning("Property not found for component property: " + component.getName() + + "/" + + componentProperty.getName(), component); + } + } + + // Create component properties for all properties + if (component.getImplementation() != null) { + for (Property property : component.getImplementation().getProperties()) { + if (!componentProperties.containsKey(property.getName())) { + ComponentProperty componentProperty = assemblyFactory.createComponentProperty(); + componentProperty.setName(property.getName()); + componentProperty.setMany(property.isMany()); + componentProperty.setXSDElement(property.getXSDElement()); + componentProperty.setXSDType(property.getXSDType()); + componentProperty.setProperty(property); + component.getProperties().add(componentProperty); + } + } + } + + // Reconcile component properties and their properties + for (ComponentProperty componentProperty : component.getProperties()) { + Property property = componentProperty.getProperty(); + if (property != null) { + + // Check that a component property does not override the + // mustSupply attribute + if (!property.isMustSupply() && componentProperty.isMustSupply()) { + warning("Component property mustSupply attribute incompatible with property: " + component + .getName() + + "/" + + componentProperty.getName(), + component); + } + + // Default to the mustSupply attribute specified on the property + if (!componentProperty.isMustSupply()) + componentProperty.setMustSupply(property.isMustSupply()); + + // Default to the value specified on the property + if (componentProperty.getValue() == null) { + componentProperty.setValue(property.getValue()); + } + + // Override the property value for the composite + if(component.getImplementation() instanceof Composite) { + property.setValue(componentProperty.getValue()); + } + + // Check that a value is supplied + if (componentProperty.getValue() == null && property.isMustSupply()) { + warning("No value configured on a mustSupply property: " + component.getName() + + "/" + + componentProperty.getName(), component); + } + + // Check that a a component property does not override the + // many attribute + if (!property.isMany() && componentProperty.isMany()) { + warning("Component property many attribute incompatible with property: " + component + .getName() + + "/" + + componentProperty.getName(), + component); + } + + // Default to the many attribute defined on the property + componentProperty.setMany(property.isMany()); + + // Default to the type and element defined on the property + if (componentProperty.getXSDType() == null) { + componentProperty.setXSDType(property.getXSDType()); + } + if (componentProperty.getXSDElement() == null) { + componentProperty.setXSDElement(property.getXSDElement()); + } + + // Check that a type or element are specified + if (componentProperty.getXSDElement() == null && componentProperty.getXSDType() == null) { + warning("No type specified on component property: " + component.getName() + + "/" + + componentProperty.getName(), component); + } + } + } + } + + /** + * Reconcile component references with the references defined on the + * component type. + * + * @param component + * @param references + * @param componentReferences + * @param problems + */ + private void reconcileReferences(Component component, + Map references, + Map componentReferences) { + + // Connect each component reference to the corresponding reference + for (ComponentReference componentReference : component.getReferences()) { + if (componentReference.getReference() != null || componentReference.isCallback()) { + continue; + } + Reference reference = references.get(componentReference.getName()); + if (reference != null) { + componentReference.setReference(reference); + } else { + if (!componentReference.getName().startsWith("$self$.")) { + warning("Reference not found for component reference: " + component.getName() + + "/" + + componentReference.getName(), component); + } + } + } + + // Create a component reference for each reference + if (component.getImplementation() != null) { + for (Reference reference : component.getImplementation().getReferences()) { + if (!componentReferences.containsKey(reference.getName())) { + ComponentReference componentReference = + assemblyFactory.createComponentReference(); + componentReference.setIsCallback(reference.isCallback()); + componentReference.setName(reference.getName()); + componentReference.setReference(reference); + component.getReferences().add(componentReference); + } + } + } + + // Reconcile each component reference with its reference + for (ComponentReference componentReference : component.getReferences()) { + Reference reference = componentReference.getReference(); + if (reference != null) { + // Reconcile multiplicity + if (componentReference.getMultiplicity() != null) { + if (!ReferenceUtil.isValidMultiplicityOverride(reference.getMultiplicity(), + componentReference + .getMultiplicity())) { + warning("Component reference multiplicity incompatible with reference multiplicity: " + component + .getName() + + "/" + + componentReference.getName(), + component); + } + } else { + componentReference.setMultiplicity(reference.getMultiplicity()); + } + + // Reconcile interface + if (componentReference.getInterfaceContract() != null) { + if (!componentReference.getInterfaceContract().equals(reference + .getInterfaceContract())) { + if (!interfaceContractMapper.isCompatible(reference.getInterfaceContract(), + componentReference + .getInterfaceContract())) { + warning("Component reference interface incompatible with reference interface: " + component + .getName() + + "/" + + componentReference.getName(), + component); + } + } + } else { + componentReference.setInterfaceContract(reference.getInterfaceContract()); + } + + // Reconcile bindings + if (componentReference.getBindings().isEmpty()) { + componentReference.getBindings().addAll(reference.getBindings()); + } + + // Reconcile callback bindings + if (componentReference.getCallback() == null) { + componentReference.setCallback(reference.getCallback()); + if (componentReference.getCallback() == null) { + // Create an empty callback to avoid null check + componentReference.setCallback(assemblyFactory.createCallback()); + } + + } else if (componentReference.getCallback().getBindings().isEmpty() && reference + .getCallback() != null) { + componentReference.getCallback().getBindings().addAll(reference.getCallback() + .getBindings()); + } + + // Propagate autowire setting from the component + if (componentReference.getAutowire() == null) { + componentReference.setAutowire(component.getAutowire()); + } + + // Reconcile targets + if (componentReference.getTargets().isEmpty()) { + componentReference.getTargets().addAll(reference.getTargets()); + } + } + } + } + + /** + * Reconcile component services and services defined on the component type. + * + * @param component + * @param services + * @param componentServices + * @param problems + */ + private void reconcileServices(Component component, + Map services, + Map componentServices) { + + // Connect each component service to the corresponding service + for (ComponentService componentService : component.getServices()) { + if (componentService.getService() != null || componentService.isCallback()) { + continue; + } + Service service = services.get(componentService.getName()); + if (service != null) { + componentService.setService(service); + } else { + warning("Service not found for component service: " + component.getName() + + "/" + + componentService.getName(), component); + } + } + + // Create a component service for each service + if (component.getImplementation() != null) { + for (Service service : component.getImplementation().getServices()) { + if (!componentServices.containsKey(service.getName())) { + ComponentService componentService = assemblyFactory.createComponentService(); + componentService.setIsCallback(service.isCallback()); + String name = service.getName(); + componentService.setName(name); + componentService.setService(service); + component.getServices().add(componentService); + componentServices.put(name, componentService); + } + } + } + + //Reconcile each component service with its service + for (ComponentService componentService : component.getServices()) { + Service service = componentService.getService(); + if (service != null) { + // Reconcile interface + if (componentService.getInterfaceContract() != null) { + if (!componentService.getInterfaceContract().equals(service + .getInterfaceContract())) { + if (!interfaceContractMapper.isCompatible(componentService + .getInterfaceContract(), service.getInterfaceContract())) { + warning("Component service interface incompatible with service interface: " + component + .getName() + + "/" + + componentService.getName(), + component); + } + } + } else { + componentService.setInterfaceContract(service.getInterfaceContract()); + } + + // Reconcile bindings + if (componentService.getBindings().isEmpty()) { + componentService.getBindings().addAll(service.getBindings()); + } + + // Reconcile callback bindings + if (componentService.getCallback() == null) { + componentService.setCallback(service.getCallback()); + if (componentService.getCallback() == null) { + // Create an empty callback to avoid null check + componentService.setCallback(assemblyFactory.createCallback()); + } + } else if (componentService.getCallback().getBindings().isEmpty() && service + .getCallback() != null) { + componentService.getCallback().getBindings().addAll(service.getCallback() + .getBindings()); + } + } + } + } + + private void indexComponentPropertiesServicesAndReferences(Component component, + Map componentServices, + Map componentReferences, + Map componentProperties) { + for (ComponentService componentService : component.getServices()) { + if (componentServices.containsKey(componentService.getName())) { + warning("Duplicate component service name: " + component.getName() + + "/" + + componentService.getName(), component); + } else { + componentServices.put(componentService.getName(), componentService); + } + } + for (ComponentReference componentReference : component.getReferences()) { + if (componentReferences.containsKey(componentReference.getName())) { + warning("Duplicate component reference name: " + component.getName() + + "/" + + componentReference.getName(), component); + } else { + componentReferences.put(componentReference.getName(), componentReference); + } + } + for (ComponentProperty componentProperty : component.getProperties()) { + if (componentProperties.containsKey(componentProperty.getName())) { + warning("Duplicate component property name: " + component.getName() + + "/" + + componentProperty.getName(), component); + } else { + componentProperties.put(componentProperty.getName(), componentProperty); + } + } + + } + + private void indexImplementationPropertiesServicesAndReferences(Component component, + Map services, + Map references, + Map properties) { + // First check that the component has a resolved implementation + Implementation implementation = component.getImplementation(); + if (implementation == null) { + + // A component must have an implementation + warning("No implementation for component: " + component.getName(), component); + + } else if (implementation.isUnresolved()) { + + // The implementation must be fully resolved + warning("Component implementation not found: " + component.getName() + + " : " + + implementation.getURI(), component); + + } else { + + // Index properties, services and references, also check for + // duplicates + for (Property property : implementation.getProperties()) { + if (properties.containsKey(property.getName())) { + warning("Duplicate property name: " + component.getName() + + "/" + + property.getName(), component); + } else { + properties.put(property.getName(), property); + } + } + for (Service service : implementation.getServices()) { + if (services.containsKey(service.getName())) { + warning("Duplicate service name: " + component.getName() + + "/" + + service.getName(), component); + } else { + services.put(service.getName(), service); + } + } + for (Reference reference : implementation.getReferences()) { + if (references.containsKey(reference.getName())) { + warning("Duplicate reference name: " + component.getName() + + "/" + + reference.getName(), component); + } else { + references.put(reference.getName(), reference); + } + } + } + + } + + /** + * For all the references with callbacks, create a corresponding callback + * service. + * + * @param component + */ + private void configureCallbackServices(Component component, + Map componentServices) { + for (ComponentReference reference : component.getReferences()) { + if (reference.getInterfaceContract() != null && // can be null in + // unit tests + reference.getInterfaceContract().getCallbackInterface() != null) { + ComponentService service = + componentServices.get(reference.getName()); + if (service == null) { + service = createCallbackService(component, reference); + } + if (reference.getCallback() != null) { + if (service.getBindings().isEmpty()) { + service.getBindings().addAll(reference.getCallback().getBindings()); + } + } + reference.setCallbackService(service); + } + } + } + + /** + * Create a callback service for a component reference + * + * @param component + * @param reference + */ + private ComponentService createCallbackService(Component component, ComponentReference reference) { + ComponentService componentService = assemblyFactory.createComponentService(); + componentService.setIsCallback(true); + componentService.setName(reference.getName()); + try { + InterfaceContract contract = + (InterfaceContract)reference.getInterfaceContract().clone(); + contract.setInterface(contract.getCallbackInterface()); + contract.setCallbackInterface(null); + componentService.setInterfaceContract(contract); + } catch (CloneNotSupportedException e) { + // will not happen + } + Reference implReference = reference.getReference(); + if (implReference != null) { + Service implService = assemblyFactory.createService(); + implService.setName(implReference.getName()); + try { + InterfaceContract implContract = + (InterfaceContract)implReference.getInterfaceContract().clone(); + implContract.setInterface(implContract.getCallbackInterface()); + implContract.setCallbackInterface(null); + implService.setInterfaceContract(implContract); + } catch (CloneNotSupportedException e) { + // will not happen + } + componentService.setService(implService); + } + component.getServices().add(componentService); + return componentService; + } + + /** + * For all the services with callbacks, create a corresponding callback + * reference. + * + * @param component + */ + private void configureCallbackReferences(Component component, + Map componentReferences) { + for (ComponentService service : component.getServices()) { + if (service.getInterfaceContract() != null && // can be null in + // unit tests + service.getInterfaceContract().getCallbackInterface() != null) { + ComponentReference reference = + componentReferences.get(service.getName()); + if (reference == null) { + reference = createCallbackReference(component, service); + } + if (service.getCallback() != null) { + if (reference.getBindings().isEmpty()) { + reference.getBindings().addAll(service.getCallback().getBindings()); + } + } + service.setCallbackReference(reference); + } + } + } + + /** + * Create a callback reference for a component service + * + * @param component + * @param service + */ + private ComponentReference createCallbackReference(Component component, ComponentService service) { + ComponentReference componentReference = assemblyFactory.createComponentReference(); + componentReference.setIsCallback(true); + componentReference.setName(service.getName()); + try { + InterfaceContract contract = (InterfaceContract)service.getInterfaceContract().clone(); + contract.setInterface(contract.getCallbackInterface()); + contract.setCallbackInterface(null); + componentReference.setInterfaceContract(contract); + } catch (CloneNotSupportedException e) { + // will not happen + } + Service implService = service.getService(); + if (implService != null) { + Reference implReference = assemblyFactory.createReference(); + implReference.setName(implService.getName()); + try { + InterfaceContract implContract = + (InterfaceContract)implService.getInterfaceContract().clone(); + implContract.setInterface(implContract.getCallbackInterface()); + implContract.setCallbackInterface(null); + implReference.setInterfaceContract(implContract); + } catch (CloneNotSupportedException e) { + // will not happen + } + componentReference.setReference(implReference); + } + component.getReferences().add(componentReference); + return componentReference; + } + + /** + * Activate composite services in nested composites. + * + * @param composite + * @param problems + */ + public void activateCompositeServices(Composite composite) { + + // Process nested composites recursively + activateNestedCompositeServices(composite); + + // Process top level composite services + for (Service service : composite.getServices()) { + CompositeService compositeService = (CompositeService)service; + + // Get the inner most promoted service + ComponentService promotedService = getPromotedComponentService(compositeService); + if (promotedService != null) { + Component promotedComponent = getPromotedComponent(compositeService); + + // Default to use the interface from the promoted service + if (compositeService.getInterfaceContract() == null && promotedService.getInterfaceContract() != null) { + compositeService.setInterfaceContract(promotedService.getInterfaceContract()); + } + + // Create a new component service to represent this composite + // service on the promoted component + ComponentService newComponentService = assemblyFactory.createComponentService(); + newComponentService.setName("$promoted$." + compositeService.getName()); + promotedComponent.getServices().add(newComponentService); + newComponentService.setService(promotedService.getService()); + newComponentService.getBindings().addAll(compositeService.getBindings()); + newComponentService.setInterfaceContract(compositeService.getInterfaceContract()); + if (compositeService.getInterfaceContract() != null && compositeService + .getInterfaceContract().getCallbackInterface() != null) { + newComponentService.setCallback(assemblyFactory.createCallback()); + if (compositeService.getCallback() != null) { + newComponentService.getCallback().getBindings().addAll(compositeService + .getCallback().getBindings()); + } + } + + // Change the composite service to now promote the newly + // created component service directly + compositeService.setPromotedComponent(promotedComponent); + compositeService.setPromotedService(newComponentService); + } + } + } + + /** + * Activate composite services in nested composites. + * + * @param composite + * @param problems + */ + public void activateNestedCompositeServices(Composite composite) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // First process nested composites + activateNestedCompositeServices((Composite)implementation); + + // Process the component services declared on components + // in this composite + for (ComponentService componentService : component.getServices()) { + Service implService = componentService.getService(); + if (implService != null && implService instanceof CompositeService) { + CompositeService compositeService = (CompositeService)implService; + + // Get the inner most promoted service + ComponentService promotedService = + getPromotedComponentService(compositeService); + if (promotedService != null) { + Component promotedComponent = getPromotedComponent(compositeService); + + // Default to use the interface from the promoted + // service + if (compositeService.getInterfaceContract() == null) { + compositeService.setInterfaceContract(promotedService + .getInterfaceContract()); + } + if (componentService.getInterfaceContract() == null) { + componentService.setInterfaceContract(promotedService + .getInterfaceContract()); + } + + // Create a new component service to represent this + // composite service on the promoted component + ComponentService newComponentService = + assemblyFactory.createComponentService(); + newComponentService.setName("$promoted$." + compositeService.getName()); + promotedComponent.getServices().add(newComponentService); + newComponentService.setService(promotedService.getService()); + newComponentService.getBindings() + .addAll(compositeService.getBindings()); + newComponentService.setInterfaceContract(compositeService + .getInterfaceContract()); + if (compositeService.getInterfaceContract() != null && compositeService + .getInterfaceContract().getCallbackInterface() != null) { + newComponentService.setCallback(assemblyFactory.createCallback()); + if (compositeService.getCallback() != null) { + newComponentService.getCallback().getBindings() + .addAll(compositeService.getCallback().getBindings()); + } + } + + // Change the composite service to now promote the + // newly created component service directly + compositeService.setPromotedComponent(promotedComponent); + compositeService.setPromotedService(newComponentService); + } + } + } + } + } + } + + /** + * @param composite + */ + private void configureSourcedProperties(Composite composite, List propertySettings) { + // Resolve properties + Map compositeProperties = new HashMap(); + ComponentProperty componentProperty = null; + for (Property p : composite.getProperties()) { + componentProperty = getComponentPropertyByName(p.getName(), propertySettings); + if (componentProperty != null) { + compositeProperties.put(p.getName(), componentProperty); + } else { + compositeProperties.put(p.getName(), p); + } + } + + for (Component component : composite.getComponents()) { + try { + PropertyUtil.sourceComponentProperties(compositeProperties, component); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + Implementation impl = component.getImplementation(); + if (impl instanceof Composite) { + configureSourcedProperties((Composite)impl, component.getProperties()); + } + } + } + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + static 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 inner most (non composite) + * component. + * + * @param compositeService + * @return + */ + private static 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; + } + } + + private ComponentProperty getComponentPropertyByName(String propertyName, List properties) { + if (properties != null) { + for (ComponentProperty aProperty : properties) { + if (aProperty.getName().equals(propertyName)) { + return aProperty; + } + } + } + return null; + } + + private SCABinding createSCABinding() { + SCABinding scaBinding = scaBindingFactory.createSCABinding(); + + if ( scaDefinitions != null ) { + for ( IntentAttachPointType attachPointType : scaDefinitions.getBindingTypes() ) { + if ( attachPointType.getName().equals(BINDING_SCA_QNAME)) { + ((IntentAttachPoint)scaBinding).setType(attachPointType); + } + } + } + + return scaBinding; + } + + /** + * Fully resolve the binding URIs based on available information. This includes information + * from the ".composite" files, from resources associated with the binding, e.g. WSDL files, + * from any associated policies and from the default information for each binding type. + * + * TODO: Share the URL calculation algorithm with the configureComponents() method above + * although keeping the configureComponents() methods signature as is because when + * a composite is actually build in a node the node default information is currently + * available + * + * @param composite the composite to be configured + * @param uri the path to the composite provided through any nested composite component implementations + * @param defaultBindings list of default binding configurations + */ + public void configureBindingURIs(Composite composite, String uri, List defaultBindings) throws CompositeBuilderException { + + String parentComponentURI = uri; + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + + // Initialize component URI + String componentURI; + if (parentComponentURI == null) { + componentURI = component.getName(); + } else { + componentURI = URI.create(parentComponentURI + '/').resolve(component.getName()).toString(); + } + component.setURI(componentURI); + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + + // Process nested composite + configureBindingURIs((Composite)implementation, componentURI, defaultBindings); + } + } + + // Initialize composite service binding URIs + List compositeServices = composite.getServices(); + for (Service service : compositeServices) { + // Set default binding names + + // Create default SCA binding + if (service.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + service.getBindings().add(scaBinding); + } + + // Initialize binding names and URIs + for (Binding binding : service.getBindings()) { + constructBindingName(service, binding); + constructBindingURI(parentComponentURI, composite, service, binding, defaultBindings); + } + } + + // Initialize component service binding URIs + for (Component component : composite.getComponents()) { + + // Index properties, services and references + Map services = new HashMap(); + Map references = new HashMap(); + Map properties = new HashMap(); + indexImplementationPropertiesServicesAndReferences(component, + services, + references, + properties); + + // Index component services, references and properties + // Also check for duplicates + Map componentServices = + new HashMap(); + Map componentReferences = + new HashMap(); + Map componentProperties = + new HashMap(); + indexComponentPropertiesServicesAndReferences(component, + componentServices, + componentReferences, + componentProperties); + + // Reconcile component services/references/properties and + // implementation services/references and create component + // services/references/properties for the services/references + // declared by the implementation + reconcileServices(component, services, componentServices); + reconcileReferences(component, references, componentReferences); + reconcileProperties(component, properties, componentProperties); + + for (ComponentService service : component.getServices()) { + + // Create default SCA binding + if (service.getBindings().isEmpty()) { + SCABinding scaBinding = createSCABinding(); + service.getBindings().add(scaBinding); + } + + // Initialize binding names and URIs + for (Binding binding : service.getBindings()) { + + constructBindingName(service, binding); + constructBindingURI(component, service, binding, defaultBindings); + } + } + } + } + + /** + * If a binding name is not provided by the user construct it based on the service name + * + * @param service + * @param binding + */ + private void constructBindingName(Service service, Binding binding) throws CompositeBuilderException{ + + // set the default binding name if one is required + // if there is no name on the binding then set it to the service name + if (binding.getName() == null){ + binding.setName(service.getName()); + } + + // Check that multiple bindings do not have the same name + for (Binding otherBinding : service.getBindings()) { + if (otherBinding == binding) { + // Skip the current binding + continue; + } + if (binding.getClass() != otherBinding.getClass()) { + // Look for a binding of the same type + continue; + } + if (binding.getName().equals(otherBinding.getName())) { + warning("Multiple bindings for service " + + service.getName() + + " have the same binding type and name " + + binding.getName() + + ". Tuscany SCA can't create unique URIs to differentiate these bindings ", binding); + } + } + } + + /** + * URI construction for composite bindings based on Assembly Specification section 1.7.2, This method + * assumes that the component URI part of the binding URI is formed from the part to the + * composite in question and just calls the generic constructBindingURI method with this + * information + * + * @param parentComponentURI + * @param composite + * @param service + * @param binding + * @param defaultBindings + */ + private void constructBindingURI(String parentComponentURI, Composite composite, Service service, Binding binding, List defaultBindings) + throws CompositeBuilderException{ + // This is a composite service so there is no component to provide a component URI + // The path to this composite (through nested composites) is used. + boolean includeBindingName = composite.getServices().size() != 1; + constructBindingURI(parentComponentURI, service, binding, includeBindingName, defaultBindings); + } + + /** + * URI construction for component bindings based on Assembly Specification section 1.7.2. This method + * calculates the component URI part based on component information before calling the generic + * constructBindingURI method + * + * @param component the component that holds the service + * @param service the service that holds the binding + * @param binding the binding for which the URI is being constructed + * @param defaultBindings the list of default binding configurations + */ + private void constructBindingURI(Component component, Service service, Binding binding, List defaultBindings) + throws CompositeBuilderException{ + boolean includeBindingName = component.getServices().size() != 1; + constructBindingURI(component.getURI(), service, binding, includeBindingName, defaultBindings); + } + + /** + * Generic URI construction for bindings based on Assembly Specification section 1.7.2 + * + * @param componentURIString the string version of the URI part that comes from the component name + * @param service the service in question + * @param binding the binding for which the URI is being constructed + * @param includeBindingName when set true the serviceBindingURI part should be used + * @param defaultBindings the list of default binding configurations + * @throws CompositeBuilderException + */ + private void constructBindingURI(String componentURIString, Service service, Binding binding, boolean includeBindingName, List defaultBindings) + throws CompositeBuilderException{ + + try { + // calculate the service binding URI + URI bindingURI; + if (binding.getURI() != null){ + bindingURI = new URI(binding.getURI()); + + // if the user has provided an absolute binding URI then use it + if (bindingURI.isAbsolute()){ + binding.setURI(bindingURI.toString()); + return; + } + } else { + bindingURI = null; + } + + // Get the service binding name + URI bindingName; + if (binding.getName() != null) { + bindingName = new URI(binding.getName()); + } else { + bindingName = new URI(""); + } + + // calculate the component URI + URI componentURI; + if (componentURIString != null) { + componentURI = new URI(addSlashToPath(componentURIString)); + } else { + componentURI = null; + } + + // if the user has provided an absolute component URI then use it + if (componentURI != null && componentURI.isAbsolute()){ + binding.setURI(constructBindingURI(null, componentURI, bindingURI, includeBindingName, bindingName)); + return; + } + + // calculate the base URI + + // get the protocol for this binding/URI +/* some code that allows binding specific code to run. Being discussed on ML + BindingURICalculator uriCalculator = bindingURICalcualtorExtensionPoint.getBindingURICalculator(binding); + + if (uriCalculator != null){ + String protocol = uriCalculator.getProtocol(binding); + + // find the default binding with the right protocol + Binding defaultBinding = nodeInfo.getBindingDefault(binding, protocol); + + if (defaultBinding != null){ + baseURI = new URI(defaultBinding.getURI()); + } else { + baseURI = null; + } + + } else { + baseURI = null; + } +*/ + // as a simpler alternative to the above commented out code. + URI baseURI = null; + if (defaultBindings != null) { + for (Binding defaultBinding : defaultBindings){ + if (binding.getClass() == defaultBinding.getClass()){ + baseURI = new URI(addSlashToPath(defaultBinding.getURI())); + break; + } + } + } + + binding.setURI(constructBindingURI(baseURI, componentURI, bindingURI, includeBindingName, bindingName)); + } catch (URISyntaxException ex) { + warning("URLSyntaxException when creating binding URI at component " + + componentURIString + + " service " + + service.getName() + + " binding " + + binding.getName(), + ex); + } + } + + /** + * Use to ensure that URI paths end in "/" as here we want to maintain the + * last path element of an base URI when other URI are resolved against it. This is + * not the default behaviour of URI resolution as defined in RFC 2369 + * + * @param path the path string to which the "/" is to be added + * @return the resulting path with a "/" added if it not already there + */ + private String addSlashToPath(String path){ + if (path.endsWith("/")){ + return path; + } else { + return path + "/"; + } + } + + /** + * Concatenate binding URI parts together based on Assembly Specification section 1.7.2 + * + * @param baseURI the base of the binding URI + * @param componentURI the middle part of the binding URI derived from the component name + * @param bindingURI the end part of the binding URI + * @param includeBindingName when set true the binding name part should be used + * @param bindingName the binding name + * @return the resulting URI as a string + */ + private String constructBindingURI(URI baseURI, URI componentURI, URI bindingURI, boolean includeBindingName, URI bindingName){ + String uriString; + + if (baseURI == null) { + if (componentURI == null){ + if (bindingURI != null ) { + uriString = bindingURI.toString(); + } else { + uriString = bindingName.toString(); + } + } else { + if (bindingURI != null ) { + uriString = componentURI.resolve(bindingURI).toString(); + } else { + if (includeBindingName) { + uriString = componentURI.resolve(bindingName).toString(); + } else { + uriString = componentURI.toString(); + } + } + } + } else { + if (componentURI == null){ + if (bindingURI != null ) { + uriString = baseURI.resolve(bindingURI).toString(); + } else { + if (includeBindingName) { + uriString = baseURI.resolve(bindingName).toString(); + } else { + uriString = baseURI.toString(); + } + } + } else { + if (bindingURI != null ) { + uriString = baseURI.resolve(componentURI).resolve(bindingURI).toString(); + } else { + if (includeBindingName) { + uriString = baseURI.resolve(componentURI).resolve(bindingName).toString(); + } else { + uriString = baseURI.resolve(componentURI).toString(); + } + } + } + } + + // tidy up by removing any trailing "/" + if (uriString.endsWith("/")){ + uriString = uriString.substring(0, uriString.length()-1); + } + + URI uri = URI.create(uriString); + if (!uri.isAbsolute()) { + uri = URI.create("/").resolve(uri); + } + return uri.toString(); + } + + public SCADefinitions getScaDefinitions() { + return scaDefinitions; + } + + public void setScaDefinitions(SCADefinitions scaDefinitions) { + this.scaDefinitions = scaDefinitions; + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.java new file mode 100644 index 0000000000..cda3c5b91a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeIncludeBuilderImpl.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.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +public class CompositeIncludeBuilderImpl { + + public static Logger logger = Logger.getLogger(CompositeIncludeBuilderImpl.class.getName()); + + public CompositeIncludeBuilderImpl(CompositeBuilderMonitor monitor) { + } + + /** + * Collect all includes in a graph of includes. + * + * @param composite + * @param includes + */ + private void collectIncludes(Composite composite, List includes, Set visited) { + for (Composite include : composite.getIncludes()) { + if (visited.contains(include)) { + logger.warning("Composite " + include.getName() + " has already been included."); + continue; + } + + includes.add(include); + visited.add(include); + collectIncludes(include, includes, visited); + } + } + + /** + * Copy a list of includes into a composite. + * + * @param composite + */ + public void fuseIncludes(Composite composite) { + + // First collect all includes + List includes = new ArrayList(); + Set visited = new HashSet(); + visited.add(composite); + collectIncludes(composite, includes, visited); + // Then clone them + for (Composite include : includes) { + Composite clone; + try { + clone = (Composite)include.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + composite.getComponents().addAll(clone.getComponents()); + composite.getServices().addAll(clone.getServices()); + composite.getReferences().addAll(clone.getReferences()); + composite.getProperties().addAll(clone.getProperties()); + composite.getWires().addAll(clone.getWires()); + if ( composite instanceof PolicySetAttachPoint ) { + ((PolicySetAttachPoint)composite).getPolicySets().addAll(((PolicySetAttachPoint)clone).getPolicySets()); + ((PolicySetAttachPoint)composite).getRequiredIntents().addAll(((PolicySetAttachPoint)clone).getRequiredIntents()); + } + } + + // Clear the list of includes + composite.getIncludes().clear(); + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeWireBuilderImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeWireBuilderImpl.java new file mode 100644 index 0000000000..c7a4990230 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeWireBuilderImpl.java @@ -0,0 +1,998 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +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.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.OptimizableBinding; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.Wire; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; +import org.apache.tuscany.sca.assembly.builder.Problem.Severity; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.policy.util.PolicyComputationUtils; + +public class CompositeWireBuilderImpl { + + private CompositeBuilderMonitor monitor; + private AssemblyFactory assemblyFactory; + private InterfaceContractMapper interfaceContractMapper; + + private BindingPolicyComputer bindingPolicyComputer = null; + private ImplementationPolicyComputer implPolicyComputer = null; + + //Represents a target component and service + private class Target { + Component component; + ComponentService service; + + Target(Component component, ComponentService service) { + this.component = component; + this.service = service; + } + + Component getComponent() { + return component; + } + + ComponentService getService() { + return service; + } + }; + + public CompositeWireBuilderImpl(AssemblyFactory assemblyFactory, InterfaceContractMapper interfaceContractMapper, CompositeBuilderMonitor monitor) { + this.assemblyFactory = assemblyFactory; + this.interfaceContractMapper = interfaceContractMapper; + this.monitor = monitor; + + this.bindingPolicyComputer = new BindingPolicyComputer(); + this.implPolicyComputer = new ImplementationPolicyComputer(); + } + + /** + * Wire component references to component services and connect promoted + * services/references to component services/references inside a composite. + * + * @param composite + */ + public void wireComposite(Composite composite) { + + // Wire nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + wireComposite((Composite)implementation); + } + } + + // Index components, services and references + Map components = new HashMap(); + Map componentServices = new HashMap(); + Map componentReferences = new HashMap(); + indexComponentsServicesAndReferences(composite, components, componentServices, componentReferences); + + // Connect composite services and references to the component + // services and references that they promote + connectCompositeServices(composite, components, componentServices); + connectCompositeReferences(composite, componentReferences); + + // Compute the policies before connecting component references + computePolicies(composite); + + // Connect component references as described in wires + connectWires(composite, componentServices, componentReferences); + + // Connect component references to their targets + connectComponentReferences(composite, components, componentServices, componentReferences); + + // Validate that references are wired or promoted, according + // to their multiplicity + for (ComponentReference componentReference : componentReferences.values()) { + if (!ReferenceUtil.validateMultiplicityAndTargets(componentReference.getMultiplicity(), componentReference + .getTargets(), componentReference.getBindings())) { + if (componentReference.getTargets().isEmpty()) { + + // No warning if the reference is promoted out of the current composite + boolean promoted = false; + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + if (compositeReference.getPromotedReferences().contains(componentReference)) { + promoted = true; + break; + } + } + if (!promoted && !componentReference.isCallback()) { + warning("No targets for reference: " + componentReference.getName(), composite); + } + } else { + warning("Too many targets on reference: " + componentReference.getName(), composite); + } + } + } + } + + /** + * Index components, services and references inside a composite. + * @param composite + * @param components + * @param componentServices + * @param componentReferences + */ + private void indexComponentsServicesAndReferences(Composite composite, + Map components, + Map componentServices, + Map componentReferences) { + + for (Component component : composite.getComponents()) { + + // Index components by name + components.put(component.getName(), component); + + ComponentService nonCallbackService = null; + int nonCallbackServices = 0; + for (ComponentService componentService : component.getServices()) { + + // Index component services by component name / service name + String uri = component.getName() + '/' + componentService.getName(); + componentServices.put(uri, componentService); + if (!componentService.isCallback()) { + + // Check how many non callback services we have + if (nonCallbackServices == 0) { + nonCallbackService = componentService; + } + nonCallbackServices++; + } + } + if (nonCallbackServices == 1) { + // If we have a single non callback service, index it by + // component name as well + componentServices.put(component.getName(), nonCallbackService); + } + + // Index references by component name / reference name + for (ComponentReference componentReference : component.getReferences()) { + String uri = component.getName() + '/' + componentReference.getName(); + componentReferences.put(uri, componentReference); + } + } + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(String message, Object model) { + monitor.problem(new ProblemImpl(Severity.WARNING, message, model)); + } + + /** + * Connect composite services to the component services that they promote. + * + * @param composite + * @param componentServices + * @param problems + */ + private void connectCompositeServices(Composite composite, + Map components, + Map componentServices) { + + // Propagate interfaces from inner composite components' services to + // their component services + for (Component component : composite.getComponents()) { + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + Service service = componentService.getService(); + if (service != null) { + if (componentService.getInterfaceContract() == null) { + componentService.setInterfaceContract(service.getInterfaceContract()); + } + } + } + } + } + + // Connect composite services to the component services that they + // promote + for (Service service : composite.getServices()) { + CompositeService compositeService = (CompositeService)service; + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null && componentService.isUnresolved()) { + + String promotedComponentName = compositeService.getPromotedComponent().getName(); + String promotedServiceName; + if (componentService.getName() != null) { + promotedServiceName = promotedComponentName + '/' + componentService.getName(); + } else { + promotedServiceName = promotedComponentName; + } + ComponentService promotedService = componentServices.get(promotedServiceName); + if (promotedService != null) { + + // Point to the resolved component + Component promotedComponent = components.get(promotedComponentName); + compositeService.setPromotedComponent(promotedComponent); + + // Point to the resolved component service + compositeService.setPromotedService(promotedService); + + // Use the interface contract from the component service if + // none is specified on the composite service + if (compositeService.getInterfaceContract() == null) { + compositeService.setInterfaceContract(promotedService.getInterfaceContract()); + } + + } else { + warning("Promoted component service not found: " + promotedServiceName, composite); + } + } + } + + } + + /** + * Resolves promoted references. + * + * @param composite + * @param componentReferences + * @param problems + */ + private void connectCompositeReferences(Composite composite, Map componentReferences) { + + // Propagate interfaces from inner composite components' references to + // their component references + for (Component component : composite.getComponents()) { + if (component.getImplementation() instanceof Composite) { + for (ComponentReference componentReference : component.getReferences()) { + Reference reference = componentReference.getReference(); + if (reference != null) { + if (componentReference.getInterfaceContract() == null) { + componentReference.setInterfaceContract(reference.getInterfaceContract()); + } + } + } + } + } + + // Connect composite references to the component references + // that they promote + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + List promotedReferences = compositeReference.getPromotedReferences(); + for (int i = 0, n = promotedReferences.size(); i < n; i++) { + ComponentReference componentReference = promotedReferences.get(i); + if (componentReference.isUnresolved()) { + String componentReferenceName = componentReference.getName(); + componentReference = componentReferences.get(componentReferenceName); + if (componentReference != null) { + + // Point to the resolved component reference + promotedReferences.set(i, componentReference); + + // Use the interface contract from the component + // reference if none + // is specified on the composite reference + if (compositeReference.getInterfaceContract() == null) { + compositeReference.setInterfaceContract(componentReference.getInterfaceContract()); + } + + } else { + warning("Promoted component reference not found: " + componentReferenceName, composite); + } + } + } + } + } + + private List createComponentReferenceTargets(Composite composite, + Map components, + Map componentServices, + ComponentReference componentReference) { + List targets = new ArrayList(); + + if (componentReference.getAutowire() == Boolean.TRUE) { + + // Find suitable targets in the current composite for an + // autowired reference + Multiplicity multiplicity = componentReference.getMultiplicity(); + for (Component targetComponent : composite.getComponents()) { + for (ComponentService targetComponentService : targetComponent.getServices()) { + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + Target target = new Target(targetComponent, targetComponentService); + targets.add(target); + if (multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) { + break; + } + } + } + } + + if (multiplicity == Multiplicity.ONE_N || multiplicity == Multiplicity.ONE_ONE) { + if (targets.size() == 0) { + warning("No target services found for the component reference to be autowired: " + componentReference + .getName(), + componentReference); + } + } + + } else if (!componentReference.getTargets().isEmpty()) { + + // Resolve targets specified on the component reference + for (ComponentService componentService : componentReference.getTargets()) { + + // Resolve the target component and service + String name = componentService.getName(); + ComponentService targetComponentService = componentServices.get(name); + Component targetComponent; + int s = name.indexOf('/'); + if (s == -1) { + targetComponent = components.get(name); + } else { + targetComponent = components.get(name.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of the component reference interface + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + Target target = new Target(targetComponent, targetComponentService); + targets.add(target); + + // mark the reference target as resolved. Used later when we are looking to + // see if an sca binding is associated with a resolved target or not + componentService.setUnresolved(false); + } else { + warning("Incompatible interfaces on component reference and target: " + componentReference + .getName() + + " : " + + componentService.getName(), + composite); + } + } else { + // add all the reference bindings into the target so that they + // can be used for comparison when the target is resolved at runtime + componentService.getBindings().addAll(componentReference.getBindings()); + + // The bindings will be cloned back into the reference when the + // target is finally resolved. + + warning("Component reference target not found, it might be a remote service: " + componentService.getName(), composite); + } + } + } else if (componentReference.getReference() != null) { + + // Resolve targets from the corresponding reference in the + // componentType + for (ComponentService componentService : componentReference.getReference().getTargets()) { + + // Resolve the target component and service + String name = componentService.getName(); + ComponentService targetComponentService = componentServices.get(name); + Component targetComponent; + int s = name.indexOf('/'); + if (s == -1) { + targetComponent = components.get(name); + } else { + targetComponent = components.get(name.substring(0, s)); + } + + if (targetComponentService != null) { + + // Check that the target component service provides + // a superset of + // the component reference interface + if (componentReference.getInterfaceContract() == null || + interfaceContractMapper.isCompatible(componentReference.getInterfaceContract(), targetComponentService.getInterfaceContract())) { + + Target target = new Target(targetComponent, targetComponentService); + targets.add(target); + + // mark the reference target as resolved. Used later when we are looking to + // see if an sca binding is associated with a resolved target or not + componentService.setUnresolved(false); + } else { + warning("Incompatible interfaces on component reference and target: " + componentReference + .getName() + + " : " + + componentService.getName(), + composite); + } + } else { + // add all the reference bindings into the target so that they + // can be used for comparison when the target is resolved at runtime + componentService.getBindings().addAll(componentReference.getBindings()); + + // The bindings will be cloned back into the reference when the + // target is finally resolved. + + warning("Component reference target from component type not found, it might be a remote service: " + componentService.getName(), composite); + } + } + } + return targets; + } + + + /** + * Connect references to their targets. + * + * @param composite + * @param componentServices + * @param componentReferences + * @param problems + */ + private void connectComponentReferences(Composite composite, + Map components, + Map componentServices, + Map componentReferences) { + for (ComponentReference componentReference : componentReferences.values()) { + + List targets = createComponentReferenceTargets(composite, + components, + componentServices, + componentReference); + + // Select the reference bindings matching the target service bindings + List selectedBindings = new ArrayList(); + + // Handle callback + boolean bidirectional = false; + if (componentReference.getInterfaceContract() != null && componentReference.getInterfaceContract().getCallbackInterface() != null) { + bidirectional = true; + } + List selectedCallbackBindings = bidirectional ? new ArrayList() : null; + + for (Target target : targets) { + + Component targetComponent = target.getComponent(); + ComponentService targetComponentService = target.getService(); + if (targetComponentService.getService() instanceof CompositeService) { + CompositeService compositeService = (CompositeService) targetComponentService.getService(); + // Find the promoted component service + targetComponentService = CompositeConfigurationBuilderImpl.getPromotedComponentService(compositeService); + } + + try { + bindingPolicyComputer.determineApplicableBindingPolicySets(componentReference, targetComponentService); + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + + // Match the binding against the bindings of the target service + Binding selected = BindingUtil.resolveBindings(componentReference, targetComponent, targetComponentService); + if (selected == null) { + warning("Component reference doesn't have a matching binding", componentReference); + } else { + selectedBindings.add(selected); + } + if (bidirectional) { + Binding selectedCallback = BindingUtil.resolveCallbackBindings(componentReference, targetComponent, targetComponentService); + if (selectedCallback != null) { + selectedCallbackBindings.add(selectedCallback); + } + } + } + + if (!targets.isEmpty()) { + + // Add all the effective bindings + componentReference.getBindings().clear(); + componentReference.getBindings().addAll(selectedBindings); + if (bidirectional) { + componentReference.getCallback().getBindings().clear(); + componentReference.getCallback().getBindings().addAll(selectedCallbackBindings); + } + } + + // Need to tidy up the reference binding list. The situation so far... + // Wired reference (1 or more targets are specified) + // Binding.uri = null - remove as its left over from target resolution + // the binding will have been moved to the target from where + // it will be resolved later + // Binding.uri != null - the reference was resolved + // Unwired reference (0 targets) + // Binding.uri = null - Either a callback reference or the reference is yet to be wired + // either manually or via autowire so leave the binding where it is + // Binding.uri != null - from the composite file so leave it + if (componentReference.getTargets().size() > 0){ + List bindingsToRemove = new ArrayList(); + for(Binding binding : componentReference.getBindings()){ + if(binding.getURI() == null){ + bindingsToRemove.add(binding); + } + } + + componentReference.getBindings().removeAll(bindingsToRemove); + } + } + } + + /** + * Resolve wires and connect the sources to their targets + * + * @param composite + * @param componentServices + * @param componentReferences + * @param problems + */ + private void connectWires(Composite composite, + Map componentServices, + Map componentReferences) { + + // For each wire, resolve the source reference, the target service, and + // add it to the list of targets of the reference + List wires = composite.getWires(); + for (int i = 0, n = wires.size(); i < n; i++) { + Wire wire = wires.get(i); + + ComponentReference resolvedReference; + ComponentService resolvedService; + + // Resolve the source reference + ComponentReference source = wire.getSource(); + if (source != null && source.isUnresolved()) { + resolvedReference = componentReferences.get(source.getName()); + if (resolvedReference != null) { + wire.setSource(resolvedReference); + } else { + warning("Wire source not found: " + source.getName(), composite); + } + } else { + resolvedReference = wire.getSource(); + } + + // Resolve the target service + ComponentService target = wire.getTarget(); + if (target != null && target.isUnresolved()) { + resolvedService = componentServices.get(target.getName()); + if (resolvedService != null) { + wire.setTarget(target); + } else { + warning("Wire target not found: " + source.getName(), composite); + } + } else { + resolvedService = wire.getTarget(); + } + + // Add the target service to the list of targets of the + // reference + if (resolvedReference != null && resolvedService != null) { + // Check that the target component service provides + // a superset of + // the component reference interface + if (resolvedReference.getInterfaceContract() == null || interfaceContractMapper + .isCompatible(resolvedReference.getInterfaceContract(), resolvedService.getInterfaceContract())) { + + //resolvedReference.getTargets().add(resolvedService); + resolvedReference.getTargets().add(wire.getTarget()); + } else { + warning("Incompatible interfaces on wire source and target: " + source.getName() + + " : " + + target.getName(), composite); + } + } + } + + // Clear the list of wires + composite.getWires().clear(); + } + + /** + * Wire composite references in nested composites. + * + * @param composite + * @param problems + */ + public void wireCompositeReferences(Composite composite) { + + // Process nested composites recursively + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + wireCompositeReferences((Composite)implementation); + } + } + + // Process composite references declared in this composite + for (Reference reference : composite.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + List promotedReferences = getPromotedComponentReferences(compositeReference); + for (ComponentReference promotedReference : promotedReferences) { + + reconcileReferenceBindings(compositeReference, promotedReference); + if (compositeReference.getInterfaceContract() != null && // can be null in unit tests + compositeReference.getInterfaceContract().getCallbackInterface() != null) { + SCABinding scaCallbackBinding = promotedReference.getCallbackBinding(SCABinding.class); + if (promotedReference.getCallback() != null) { + promotedReference.getCallback().getBindings().clear(); + } else { + promotedReference.setCallback(assemblyFactory.createCallback()); + } + if (scaCallbackBinding != null) { + promotedReference.getCallback().getBindings().add(scaCallbackBinding); + } + if (compositeReference.getCallback() != null) { + promotedReference.getCallback().getBindings().addAll(compositeReference.getCallback() + .getBindings()); + } + } + } + } + + // Process the component references declared on components + // in this composite + for (Component component : composite.getComponents()) { + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + for (ComponentReference componentReference : component.getReferences()) { + Reference implReference = componentReference.getReference(); + if (implReference != null && implReference instanceof CompositeReference) { + CompositeReference compositeReference = (CompositeReference)implReference; + List promotedReferences = + getPromotedComponentReferences(compositeReference); + for (ComponentReference promotedReference : promotedReferences) { + + // Override the configuration of the promoted reference + reconcileReferenceBindings(componentReference, promotedReference); + if (componentReference.getInterfaceContract() != null && // can be null in unit tests + componentReference.getInterfaceContract().getCallbackInterface() != null) { + SCABinding scaCallbackBinding = promotedReference.getCallbackBinding(SCABinding.class); + if (promotedReference.getCallback() != null) { + promotedReference.getCallback().getBindings().clear(); + } else { + promotedReference.setCallback(assemblyFactory.createCallback()); + } + if (scaCallbackBinding != null) { + promotedReference.getCallback().getBindings().add(scaCallbackBinding); + } + if (componentReference.getCallback() != null) { + promotedReference.getCallback().getBindings().addAll(componentReference + .getCallback().getBindings()); + } + } + + // Wire the promoted reference to the actual + // non-composite component services + if (promotedReference.getMultiplicity() == Multiplicity.ONE_ONE || promotedReference + .getMultiplicity() == Multiplicity.ONE_ONE) { + // promotedReference.getTargets().clear(); + } + for (ComponentService target : componentReference.getTargets()) { + if (target.getService() instanceof CompositeService) { + + // Wire to the actual component service + // promoted by a composite service + CompositeService compositeService = (CompositeService)target.getService(); + // Find the promoted component service + ComponentService componentService = CompositeConfigurationBuilderImpl.getPromotedComponentService(compositeService); + if (componentService != null) { + promotedReference.getTargets().add(componentService); + } + } else { + + // Wire to a non-composite target service + promotedReference.getTargets().add(target); + } + } + } + } + } + } else { + for (ComponentReference componentReference : component.getReferences()) { + + // Wire the component reference to the actual + // non-composite component services + List targets = componentReference.getTargets(); + for (int i = 0, n = targets.size(); i < n; i++) { + ComponentService target = targets.get(i); + if (target.getService() instanceof CompositeService) { + + // Wire to the actual component service + // promoted by a composite service + CompositeService compositeService = (CompositeService)target.getService(); + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + targets.set(i, componentService); + } + } + } + } + } + } + } + + /** + * Follow a reference promotion chain down to the inner most (non composite) + * component references. + * + * @param compositeReference + * @return + */ + private List getPromotedComponentReferences(CompositeReference compositeReference) { + List componentReferences = new ArrayList(); + collectPromotedComponentReferences(compositeReference, componentReferences); + return componentReferences; + } + + /** + * Follow a reference promotion chain down to the inner most (non composite) + * component references. + * + * @param compositeReference + * @param componentReferences + * @return + */ + private void collectPromotedComponentReferences(CompositeReference compositeReference, + List componentReferences) { + for (ComponentReference componentReference : compositeReference.getPromotedReferences()) { + Reference reference = componentReference.getReference(); + if (reference instanceof CompositeReference) { + + // Continue to follow the reference promotion chain + collectPromotedComponentReferences((CompositeReference)reference, componentReferences); + + } else if (reference != null) { + + // Found a non-composite reference + componentReferences.add(componentReference); + } + } + } + + /** + * Override the bindings for a promoted reference from an outer component + * reference + * + * @param reference + * @param promotedReference + */ + private void reconcileReferenceBindings(Reference reference, ComponentReference promotedReference) { + Set bindings = new HashSet(); + bindings.addAll(promotedReference.getBindings()); + bindings.addAll(reference.getBindings()); + promotedReference.getBindings().clear(); + for (Binding binding : bindings) { + if ((!(binding instanceof OptimizableBinding)) || binding.getURI() != null) { + promotedReference.getBindings().add(binding); + } + } + if (promotedReference.getMultiplicity() == Multiplicity.ONE_ONE || promotedReference.getMultiplicity() == Multiplicity.ZERO_ONE) { + if (promotedReference.getBindings().size() > 1) { + warning("Component reference " + promotedReference.getName() + " has more than one wires", + promotedReference); + } + } + Set callbackBindings = new HashSet(); + if (promotedReference.getCallback() != null) { + callbackBindings.addAll(promotedReference.getCallback().getBindings()); + } + if (reference.getCallback() != null) { + callbackBindings.addAll(reference.getCallback().getBindings()); + } + promotedReference.setCallback(assemblyFactory.createCallback()); + for (Binding binding : callbackBindings) { + if ((!(binding instanceof OptimizableBinding)) || binding.getURI() != null) { + promotedReference.getCallback().getBindings().add(binding); + } + } + } + + private void addPoliciesFromPromotedService(CompositeService compositeService) { + //inherit intents and policies from promoted service + PolicyComputationUtils.addInheritedIntents(compositeService.getPromotedService().getRequiredIntents(), + compositeService.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(compositeService.getPromotedService().getPolicySets(), + compositeService.getPolicySets(), true); + addInheritedOperationConfigurations(compositeService.getPromotedService(), compositeService); + } + + private void addPoliciesFromPromotedReference(CompositeReference compositeReference) { + for ( Reference promotedReference : compositeReference.getPromotedReferences() ) { + PolicyComputationUtils.addInheritedIntents(promotedReference.getRequiredIntents(), + compositeReference.getRequiredIntents()); + + PolicyComputationUtils.addInheritedPolicySets(promotedReference.getPolicySets(), + compositeReference.getPolicySets(), true); + addInheritedOperationConfigurations(promotedReference, compositeReference); + } + } + + + public void computePolicies(Composite composite) { + + //compute policies for composite service bindings + for (Service service : composite.getServices()) { + addPoliciesFromPromotedService((CompositeService)service); + try { + //compute the intents for operations under service element + bindingPolicyComputer.computeIntentsForOperations(service); + //add or merge service operations to the binding + //addInheritedOpConfOnBindings(service); + bindingPolicyComputer.computeBindingIntentsAndPolicySets(service); + bindingPolicyComputer.determineApplicableBindingPolicySets(service, null); + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + + } + + for (Reference reference : composite.getReferences()) { + CompositeReference compReference = (CompositeReference)reference; + addPoliciesFromPromotedReference(compReference); + try { + //compute the intents for operations under service element + bindingPolicyComputer.computeIntentsForOperations(reference); + //addInheritedOpConfOnBindings(reference); + + if (compReference.getCallback() != null) { + PolicyComputationUtils.addInheritedIntents(compReference.getRequiredIntents(), + compReference.getCallback().getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(compReference.getPolicySets(), + compReference.getCallback().getPolicySets(), + false); + } + + bindingPolicyComputer.computeBindingIntentsAndPolicySets(reference); + bindingPolicyComputer.determineApplicableBindingPolicySets(reference, null); + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + } + + for (Component component : composite.getComponents()) { + Implementation implemenation = component.getImplementation(); + try { + implPolicyComputer.computeImplementationIntentsAndPolicySets(implemenation, component); + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + + for (ComponentService componentService : component.getServices()) { + Service service = componentService.getService(); + if (service != null) { + // reconcile intents and policysets from componentType + PolicyComputationUtils.addInheritedIntents(service.getRequiredIntents(), componentService.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(service.getPolicySets(), componentService.getPolicySets(), true); + + //reconcile intents and policysets for operations + boolean notFound; + List opsFromComponentType = new ArrayList(); + for ( ConfiguredOperation ctsConfOp : service.getConfiguredOperations() ) { + notFound = true; + for ( ConfiguredOperation csConfOp : componentService.getConfiguredOperations() ) { + if ( csConfOp.getName().equals(ctsConfOp.getName()) ) { + PolicyComputationUtils.addInheritedIntents(ctsConfOp.getRequiredIntents(), csConfOp.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(ctsConfOp.getPolicySets(), csConfOp.getPolicySets(), true); + notFound = false; + } + } + + if ( notFound ) { + opsFromComponentType.add(ctsConfOp); + } + } + componentService.getConfiguredOperations().addAll(opsFromComponentType); + } + + try { + //compute the intents for operations under service element + bindingPolicyComputer.computeIntentsForOperations(componentService); + //compute intents and policyset for each binding + //addInheritedOpConfOnBindings(componentService); + bindingPolicyComputer.computeBindingIntentsAndPolicySets(componentService); + bindingPolicyComputer.determineApplicableBindingPolicySets(componentService, null); + + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + } + + for (ComponentReference componentReference : component.getReferences()) { + Reference reference = componentReference.getReference(); + if (reference != null) { + // reconcile intents and policysets + PolicyComputationUtils.addInheritedIntents(reference.getRequiredIntents(), componentReference.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(reference.getPolicySets(), componentReference.getPolicySets(), true); + } + + + try { + //compute the intents for operations under reference element + bindingPolicyComputer.computeIntentsForOperations(componentReference); + //compute intents and policyset for each binding + //addInheritedOpConfOnBindings(componentReference); + bindingPolicyComputer.computeBindingIntentsAndPolicySets(componentReference); + bindingPolicyComputer.determineApplicableBindingPolicySets(componentReference, null); + + + if ( componentReference.getCallback() != null ) { + PolicyComputationUtils.addInheritedIntents(componentReference.getRequiredIntents(), + componentReference.getCallback().getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(componentReference.getPolicySets(), + componentReference.getCallback().getPolicySets(), + false); + } + } catch ( Exception e ) { + warning("Policy related exception: " + e, e); + //throw new RuntimeException(e); + } + } + } + } + + private void addInheritedOperationConfigurations(OperationsConfigurator source, + OperationsConfigurator target) { + boolean found = false; + + List additionalOperations = new ArrayList(); + for ( ConfiguredOperation sourceConfOp : source.getConfiguredOperations() ) { + for ( ConfiguredOperation targetConfOp : target.getConfiguredOperations() ) { + if ( sourceConfOp.getName().equals(targetConfOp.getName())) { + PolicyComputationUtils.addInheritedIntents(sourceConfOp.getRequiredIntents(), + targetConfOp.getRequiredIntents()); + PolicyComputationUtils.addInheritedPolicySets(sourceConfOp.getPolicySets(), + targetConfOp.getPolicySets(), true); + found = true; + break; + } + } + + if ( !found ) { + additionalOperations.add(sourceConfOp); + } + } + + if ( !additionalOperations.isEmpty() ) { + target.getConfiguredOperations().addAll(additionalOperations); + } + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/DomainWireBuilderImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/DomainWireBuilderImpl.java new file mode 100644 index 0000000000..b2f96c30cc --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/DomainWireBuilderImpl.java @@ -0,0 +1,289 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.util.ArrayList; +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.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; +import org.apache.tuscany.sca.assembly.builder.DomainBuilder; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; + +public class DomainWireBuilderImpl implements DomainBuilder { + + private CompositeWireBuilderImpl wireBuilder; + + public DomainWireBuilderImpl(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper, + CompositeBuilderMonitor monitor) { + wireBuilder = new CompositeWireBuilderImpl(assemblyFactory, interfaceContractMapper, monitor); + } + + public String getComponentNameFromReference(String referenceName){ + // Extract the component name + String componentName = referenceName; + int i = referenceName.indexOf('/'); + if (i != -1) { + componentName = referenceName.substring(0, i); + } + + return componentName; + } + + public String getServiceNameFromReference(String referenceName){ + // Extract the component name + String serviceName = null; + int i = referenceName.indexOf('/'); + if (i != -1) { + serviceName = referenceName.substring(i + 1); + + } + return serviceName; + } + + + public List findReferenceForService(Composite composite, String serviceName){ + + List referenceList = new ArrayList(); + + String componentName = getComponentNameFromReference(serviceName); + + for (Reference reference: composite.getReferences()) { + for (ComponentService componentService : reference.getTargets()){ + if (componentService.getName().equals(serviceName) || + componentService.getName().equals(componentName)) { + referenceList.add(reference); + } + } + } + + for (Component component: composite.getComponents()) { + for (ComponentReference reference: component.getReferences()) { + for (ComponentService componentService : reference.getTargets()){ + if (componentService.getName().equals(serviceName) || + componentService.getName().equals(componentName)) { + referenceList.add(reference); + } + } + } + } + + return referenceList; + } + + public List findDomainLevelReferenceForService(Composite composite, String referenceName){ + List referenceList = new ArrayList(); + + for (Composite tmpComposite : composite.getIncludes()) { + List tmpReferenceList = findReferenceForService(tmpComposite, referenceName); + + referenceList.addAll(tmpReferenceList); + } + + return referenceList; + } + + public Service findServiceForReference(Composite composite, String referenceName){ + + String componentName = getComponentNameFromReference(referenceName); + String serviceName = getServiceNameFromReference(referenceName); + + for (Service service: composite.getServices()) { + if (service.getName().equals(serviceName)){ + return service; + } + } + + for (Component component: composite.getComponents()) { + if (component.getName().equals(componentName)){ + if (component.getServices().size() > 1) { + for (Service service: component.getServices()) { + if (service.getName().equals(serviceName)){ + return service; + } + } + } else if (component.getServices().size() == 1) { + return component.getServices().get(0); + } + } + } + + return null; + } + + public Service findDomainLevelService(Composite composite, String referenceName){ + Service service = null; + + for (Composite tmpComposite : composite.getIncludes()) { + service = findServiceForReference(tmpComposite, referenceName); + if (service != null) { + break; + } + } + + return service; + } + + public void updateDomainLevelServiceURI(Composite domainLevelComposite, String referenceName, String bindingClassName, String URI){ + + String componentName = getComponentNameFromReference(referenceName); + String serviceName = getServiceNameFromReference(referenceName); + + // get the named service + Service service = null; + for(Composite composite : domainLevelComposite.getIncludes()) { + service = findServiceForReference(composite, referenceName); + if (service != null){ + break; + } + } + + if (service != null) { + // find the named binding + for (Binding binding : service.getBindings()){ + if (binding.getClass().getName().equals(bindingClassName)){ + binding.setURI(URI); + break; + } + } + } + } + + public List wireDomain(Composite domainLevelComposite){ + List changedComposites = new ArrayList(); + + // process wires + + // autowire + + // wire by impl? + + // process all wired references + for(Composite composite : domainLevelComposite.getIncludes()) { + boolean compositeChanged = false; + for(Component component : composite.getComponents()){ + for (Reference reference : component.getReferences()){ + for (ComponentService targetService : reference.getTargets()){ + String targetName = targetService.getName(); + String componentName = getComponentNameFromReference(targetName); + String serviceName = getServiceNameFromReference(targetName); + + Service service = null; + Component serviceComponent = null; + + // find the real target service in the domain + for(Composite tmpComposite : domainLevelComposite.getIncludes()) { + for (Component tmpComponent: tmpComposite.getComponents()) { + if (tmpComponent.getName().equals(componentName)){ + serviceComponent = tmpComponent; + if (tmpComponent.getServices().size() > 1) { + for (Service tmpService: tmpComponent.getServices()) { + if (tmpService.getName().equals(serviceName)){ + service = tmpService; + break; + } + } + } else if (tmpComponent.getServices().size() == 1) { + service = tmpComponent.getServices().get(0); + break; + } + } + } + } + + if ( targetService.isUnresolved()){ + + if (service != null){ + // Find the binding already in use for this target + Binding binding = null; + + for (Binding tmpBinding : reference.getBindings()){ + if ((tmpBinding.getName() != null) && + (tmpBinding.getName().startsWith(reference.getName() + "#" + targetName))){ + binding = tmpBinding; + } + } + + // Resolve the binding that should be used for this target + // TODO - hang onto the old bindings at the domain level, i.e. + // don't rely on the target objects as we still need the + // bindings if we are going to do autowiring + List source = targetService.getBindings(); + List target = service.getBindings(); + Binding newBinding = BindingUtil.matchBinding(serviceComponent, (ComponentService)service, source, target); + + // update the existing binding to the new binding if required + if (newBinding != null) { + if (binding != null){ + // there is a binding already so see if the URI has changed + if ((binding.getURI() == null) || + (!binding.getURI().equals(newBinding.getURI()))){ + binding.setURI(newBinding.getURI()); + compositeChanged = true; + } + } else { + // this is a newly configured binding so add it + reference.getBindings().add(newBinding); + compositeChanged = true; + } + } + } else { + // Do nothing - the target service hasn't been contributed yet + } + } else { + // find the reference binding with the right name + for (Binding refBinding : reference.getBindings()){ + if ((refBinding.getName() != null) && + (refBinding.getName().startsWith(reference.getName() + "#" + targetName))){ + // find the matching service binding + for (Binding serviceBinding : service.getBindings()){ + if (refBinding.getClass() == serviceBinding.getClass()){ + refBinding.setURI(serviceBinding.getURI()); + } + } + } + } + } + } + } + } + + if (compositeChanged) { + changedComposites.add(composite); + } + } + + return changedComposites; + } + + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ImplementationPolicyComputer.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ImplementationPolicyComputer.java new file mode 100644 index 0000000000..2bd010c489 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ImplementationPolicyComputer.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.util.PolicyValidationException; + +/** + * Policy computation methods pertaining to computing Implementation Policies + */ +public class ImplementationPolicyComputer extends PolicyComputer { + + public ImplementationPolicyComputer() { + super(); + } + + public void computeImplementationIntentsAndPolicySets(Implementation implementation, Component parent) + throws PolicyValidationException, PolicyComputationException { + if ( implementation instanceof PolicySetAttachPoint ) { + PolicySetAttachPoint policiedImplementation = (PolicySetAttachPoint)implementation; + //since for an implementation the component has its policy intents and policysets its possible + //that there are some intents there that does not constrain the implementation.. so prune + List prunedIntents = computeInheritableIntents(policiedImplementation.getType(), + parent.getRequiredIntents()); + parent.getRequiredIntents().clear(); + parent.getRequiredIntents().addAll(prunedIntents); + normalizeIntents(parent); + + computeIntentsForOperations((OperationsConfigurator)parent, + (IntentAttachPoint)implementation, + parent.getRequiredIntents()); + + + List prunedPolicySets = computeInheritablePolicySets(parent.getPolicySets(), + parent.getApplicablePolicySets()); + parent.getPolicySets().clear(); + parent.getPolicySets().addAll(prunedPolicySets); + normalizePolicySets(parent); + computePolicySetsForOperations(parent.getApplicablePolicySets(), + (OperationsConfigurator)parent, + (PolicySetAttachPoint)implementation); + + determineApplicableImplementationPolicySets(parent); + } + } + + private void determineApplicableImplementationPolicySets(Component component) throws PolicyComputationException { + List intentsCopy = null; + if ( component.getImplementation() instanceof PolicySetAttachPoint ) { + PolicySetAttachPoint policiedImplementation = (PolicySetAttachPoint)component.getImplementation(); + + //trim intents specified in operations. First check for policysets specified on the operation + //and then in the parent implementation + if ( component instanceof OperationsConfigurator ) { + OperationsConfigurator opConfigurator = (OperationsConfigurator)component; + + for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) { + intentsCopy = new ArrayList(confOp.getRequiredIntents()); + trimInherentlyProvidedIntents(policiedImplementation.getType(), + confOp.getRequiredIntents()); + trimProvidedIntents(confOp.getRequiredIntents(), confOp.getPolicySets()); + trimProvidedIntents(confOp.getRequiredIntents(), component.getPolicySets()); + + determineApplicableDomainPolicySets(component.getApplicablePolicySets(), + confOp, + policiedImplementation.getType()); + + if (confOp.getRequiredIntents().size() > 0) { + new PolicyComputationException("The following are unfulfilled intents for operations configured in " + + "component implementation - " + component.getName() + "\nUnfulfilled Intents = " + + confOp.getRequiredIntents()); + } + + //the intents list could have been trimmed when matching for policysets + //since the implementation may need the original set of intents we copy that back + confOp.getRequiredIntents().clear(); + confOp.getRequiredIntents().addAll(intentsCopy); + } + } + + intentsCopy = new ArrayList(component.getRequiredIntents()); + trimInherentlyProvidedIntents(policiedImplementation.getType(), + component.getRequiredIntents()); + trimProvidedIntents(component.getRequiredIntents(), component.getPolicySets()); + + //determine additional policysets that match remaining intents + //if there are intents that are not provided by any policy set throw a warning + //TODO: resolved to domain policy registry and attach suitable policy sets to the implementation + //...for now using the SCA Definitions instead of registry + //if ( domainPolicySets != null) { + determineApplicableDomainPolicySets(component.getApplicablePolicySets(), + component, + policiedImplementation.getType()); + + if (component.getRequiredIntents().size() > 0) { + throw new PolicyComputationException("The following are unfulfilled intents for component implementation - " + component + .getName() + "\nUnfulfilled Intents = " + component.getRequiredIntents()); + } + //} + + //the intents list could have been trimmed when matching for policysets + //since the bindings may need the original set of intents we copy that back + component.getRequiredIntents().clear(); + component.getRequiredIntents().addAll(intentsCopy); + } + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputationException.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputationException.java new file mode 100644 index 0000000000..ae9ed87035 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputationException.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.assembly.builder.impl; + +/** + * Exception to be throw for invalid policy intents / policysets + */ +public class PolicyComputationException extends Exception { + private static final long serialVersionUID = 506979037642587755L; + + public PolicyComputationException(String message) { + super(message); + } + + public PolicyComputationException(Throwable e) { + super(e); + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputer.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputer.java new file mode 100644 index 0000000000..0e290865bd --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PolicyComputer.java @@ -0,0 +1,372 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.ProfileIntent; +import org.apache.tuscany.sca.policy.QualifiedIntent; +import org.apache.tuscany.sca.policy.util.PolicyValidationException; +import org.apache.tuscany.sca.policy.util.PolicyValidationUtils; + +/** + * This class contains policy computation methods common to computing implementation and binding policies + */ +public abstract class PolicyComputer { + + protected PolicyComputer() { + + } + + protected List computeInheritableIntents(IntentAttachPointType attachPointType, + List inheritableIntents) throws PolicyValidationException { + List validInheritableIntents = new ArrayList(); + + //expand profile intents in inherited intents + expandProfileIntents(inheritableIntents); + + //validate if inherited intent applies to the attachpoint (binding / implementation) and + //only add such intents to the attachpoint (binding / implementation) + for (Intent intent : inheritableIntents) { + if ( !intent.isUnresolved() ) { + for (QName constrained : intent.getConstrains()) { + if ( PolicyValidationUtils.isConstrained(constrained, attachPointType)) { + validInheritableIntents.add(intent); + break; + } + } + } else { + throw new PolicyValidationException("Policy Intent '" + intent.getName() + "' is not defined in this domain"); + } + } + + return validInheritableIntents; + } + + protected void expandProfileIntents(List intents) { + List expandedIntents = null; + if ( intents.size() > 0 ) { + expandedIntents = findAndExpandProfileIntents(intents); + intents.clear(); + intents.addAll(expandedIntents); + } + } + + protected void normalizeIntents(IntentAttachPoint intentAttachPoint) { + //expand profile intents specified in the attachpoint (binding / implementation) + expandProfileIntents(intentAttachPoint.getRequiredIntents()); + + //remove duplicates and ... + //where qualified form of intent exists retain it and remove the qualifiable intent + filterDuplicatesAndQualifiableIntents(intentAttachPoint); + } + + protected void trimInherentlyProvidedIntents(IntentAttachPointType attachPointType, Listintents) { + //exclude intents that are inherently supported by the + //attachpoint-type (binding-type / implementation-type) + List requiredIntents = new ArrayList(intents); + for ( Intent intent : requiredIntents ) { + if ( isProvidedInherently(attachPointType, intent) ) { + intents.remove(intent); + } + } + } + + + protected void computeIntentsForOperations(IntentAttachPoint intentAttachPoint) throws PolicyValidationException { + if ( intentAttachPoint instanceof OperationsConfigurator ) { + computeIntentsForOperations((OperationsConfigurator)intentAttachPoint, + intentAttachPoint, + intentAttachPoint.getRequiredIntents()); + } + } + + protected void computeIntentsForOperations(OperationsConfigurator opConfigurator, + IntentAttachPoint intentAttachPoint, + List parentIntents) throws PolicyValidationException { + IntentAttachPointType attachPointType = intentAttachPoint.getType(); + + boolean found = false; + for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) { + //expand profile intents specified on operations + expandProfileIntents(confOp.getRequiredIntents()); + + //validateIntents(confOp, attachPointType); + + //add intents specified for parent intent attach point (binding / implementation) + //wherever its not overridden in the operation + Intent tempIntent = null; + List attachPointOpIntents = new ArrayList(); + for (Intent anIntent : parentIntents) { + found = false; + + tempIntent = anIntent; + while ( tempIntent instanceof QualifiedIntent ) { + tempIntent = ((QualifiedIntent)tempIntent).getQualifiableIntent(); + } + + for ( Intent opIntent : confOp.getRequiredIntents() ) { + if ( opIntent.getName().getLocalPart().startsWith(tempIntent.getName().getLocalPart())) { + found = true; + break; + } + } + + if ( !found ) { + attachPointOpIntents.add(anIntent); + } + } + + confOp.getRequiredIntents().addAll(attachPointOpIntents); + + //remove duplicates and ... + //where qualified form of intent exists retain it and remove the qualifiable intent + filterDuplicatesAndQualifiableIntents(confOp); + + //exclude intents that are inherently supported by the parent + //attachpoint-type (binding-type / implementation-type) + if ( attachPointType != null ) { + List requiredIntents = new ArrayList(confOp.getRequiredIntents()); + for ( Intent intent : requiredIntents ) { + if ( isProvidedInherently(attachPointType, intent) ) { + confOp.getRequiredIntents().remove(intent); + } + } + } + } + } + + protected List computeInheritablePolicySets(List inheritablePolicySets, + List applicablePolicySets) + throws PolicyValidationException { + List validInheritablePolicySets = new ArrayList(); + for (PolicySet policySet : inheritablePolicySets) { + if ( !policySet.isUnresolved() ) { + if ( applicablePolicySets.contains(policySet) ) { + validInheritablePolicySets.add(policySet); + } + } else { + throw new PolicyValidationException("Policy Set '" + policySet.getName() + + "' is not defined in this domain "); + } + } + + return validInheritablePolicySets; + } + + protected void normalizePolicySets(PolicySetAttachPoint policySetAttachPoint ) { + //get rid of duplicate entries + HashMap policySetTable = new HashMap(); + for ( PolicySet policySet : policySetAttachPoint.getPolicySets() ) { + policySetTable.put(policySet.getName(), policySet); + } + + policySetAttachPoint.getPolicySets().clear(); + policySetAttachPoint.getPolicySets().addAll(policySetTable.values()); + + //expand profile intents + for ( PolicySet policySet : policySetAttachPoint.getPolicySets() ) { + expandProfileIntents(policySet.getProvidedIntents()); + } + } + + protected void computePolicySetsForOperations(List applicablePolicySets, + PolicySetAttachPoint policySetAttachPoint) + throws PolicyValidationException { + if ( policySetAttachPoint instanceof OperationsConfigurator ) { + computePolicySetsForOperations(applicablePolicySets, + (OperationsConfigurator)policySetAttachPoint, + policySetAttachPoint); + } + + } + + protected void computePolicySetsForOperations(List applicablePolicySets, + OperationsConfigurator opConfigurator, + PolicySetAttachPoint policySetAttachPoint) + throws PolicyValidationException { + //String appliesTo = null; + //String scdlFragment = ""; + HashMap policySetTable = new HashMap(); + IntentAttachPointType attachPointType = policySetAttachPoint.getType(); + + for ( ConfiguredOperation confOp : opConfigurator.getConfiguredOperations() ) { + //validate policysets specified for the attachPoint + for (PolicySet policySet : confOp.getPolicySets()) { + if ( !policySet.isUnresolved() ) { + //appliesTo = policySet.getAppliesTo(); + + //if (!PolicyValidationUtils.isPolicySetApplicable(scdlFragment, appliesTo, attachPointType)) { + if (!applicablePolicySets.contains(policySet)) { + throw new PolicyValidationException("Policy Set '" + policySet.getName() + + " specified for operation " + confOp.getName() + + "' does not constrain extension type " + + attachPointType.getName()); + + } + } else { + throw new PolicyValidationException("Policy Set '" + policySet.getName() + + " specified for operation " + confOp.getName() + + "' is not defined in this domain "); + } + } + + //get rid of duplicate entries + for ( PolicySet policySet : confOp.getPolicySets() ) { + policySetTable.put(policySet.getName(), policySet); + } + + confOp.getPolicySets().clear(); + confOp.getPolicySets().addAll(policySetTable.values()); + policySetTable.clear(); + + //expand profile intents + for ( PolicySet policySet : confOp.getPolicySets() ) { + expandProfileIntents(policySet.getProvidedIntents()); + } + } + } + + + protected void trimProvidedIntents(List requiredIntents, List policySets) { + for ( PolicySet policySet : policySets ) { + trimProvidedIntents(requiredIntents, policySet); + } + } + + protected void determineApplicableDomainPolicySets(List applicablePolicySets, + PolicySetAttachPoint policySetAttachPoint, + IntentAttachPointType intentAttachPointType) { + + if (policySetAttachPoint.getRequiredIntents().size() > 0) { + //since the set of applicable policysets for this attachpoint is known + //we only need to check in that list if there is a policyset that matches + for (PolicySet policySet : applicablePolicySets) { + int prevSize = policySetAttachPoint.getRequiredIntents().size(); + trimProvidedIntents(policySetAttachPoint.getRequiredIntents(), policySet); + // if any intent was trimmed off, then this policyset must + // be attached to the intent attachpoint's policyset + if (prevSize != policySetAttachPoint.getRequiredIntents().size()) { + policySetAttachPoint.getPolicySets().add(policySet); + } + } + } + } + + private List findAndExpandProfileIntents(List intents) { + List expandedIntents = new ArrayList(); + for ( Intent intent : intents ) { + if ( intent instanceof ProfileIntent ) { + ProfileIntent profileIntent = (ProfileIntent)intent; + List requiredIntents = profileIntent.getRequiredIntents(); + expandedIntents.addAll(findAndExpandProfileIntents(requiredIntents)); + } else { + expandedIntents.add(intent); + } + } + return expandedIntents; + } + + private boolean isProvidedInherently(IntentAttachPointType attachPointType, Intent intent) { + return ( attachPointType != null && + (( attachPointType.getAlwaysProvidedIntents() != null && + attachPointType.getAlwaysProvidedIntents().contains(intent) ) || + ( attachPointType.getMayProvideIntents() != null && + attachPointType.getMayProvideIntents().contains(intent) ) + ) ); + } + + private void trimProvidedIntents(List requiredIntents, PolicySet policySet) { + for ( Intent providedIntent : policySet.getProvidedIntents() ) { + if ( requiredIntents.contains(providedIntent) ) { + requiredIntents.remove(providedIntent); + } + } + + for ( Intent mappedIntent : policySet.getMappedPolicies().keySet() ) { + if ( requiredIntents.contains(mappedIntent) ) { + requiredIntents.remove(mappedIntent); + } + } + } + + private void filterDuplicatesAndQualifiableIntents(IntentAttachPoint intentAttachPoint) { + //remove duplicates + Map intentsTable = new HashMap(); + for ( Intent intent : intentAttachPoint.getRequiredIntents() ) { + intentsTable.put(intent.getName(), intent); + } + + //where qualified form of intent exists retain it and remove the qualifiable intent + Map intentsTableCopy = new HashMap(intentsTable); + //if qualified form of intent exists remove the unqualified form + for ( Intent intent : intentsTableCopy.values() ) { + if ( intent instanceof QualifiedIntent ) { + QualifiedIntent qualifiedIntent = (QualifiedIntent)intent; + if ( intentsTable.get(qualifiedIntent.getQualifiableIntent().getName()) != null ) { + intentsTable.remove(qualifiedIntent.getQualifiableIntent().getName()); + } + } + } + intentAttachPoint.getRequiredIntents().clear(); + intentAttachPoint.getRequiredIntents().addAll(intentsTable.values()); + } + + private void validateIntents(ConfiguredOperation confOp, IntentAttachPointType attachPointType) throws PolicyValidationException { + boolean found = false; + if ( attachPointType != null ) { + //validate intents specified against the parent (binding / implementation) + found = false; + for (Intent intent : confOp.getRequiredIntents()) { + if ( !intent.isUnresolved() ) { + for (QName constrained : intent.getConstrains()) { + if (PolicyValidationUtils.isConstrained(constrained, attachPointType)) { + found = true; + break; + } + } + + if (!found) { + throw new PolicyValidationException("Policy Intent '" + intent.getName() + + " specified for operation " + confOp.getName() + + "' does not constrain extension type " + + attachPointType.getName()); + } + } else { + throw new PolicyValidationException("Policy Intent '" + intent.getName() + + " specified for operation " + confOp.getName() + + "' is not defined in this domain "); + } + } + } + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java new file mode 100644 index 0000000000..e50d65f1d3 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtil.java @@ -0,0 +1,273 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.w3c.dom.Node; + +/** + * A simple print utility class to help print model instances. + * + * @version $Rev: 639224 $ $Date: 2008-03-20 02:37:04 -0700 (Thu, 20 Mar 2008) $ + */ +class PrintUtil { + private boolean useGetters = false; + private PrintWriter out; + private int indent; + + public PrintUtil(PrintWriter out, boolean useGetters) { + this.out = out; + this.useGetters = useGetters; + } + + public PrintUtil(OutputStream out) { + this.out = new PrintWriter(new OutputStreamWriter(out), true); + } + + void indent() { + for (int i = 0; i < indent; i++) { + out.print(" "); + } + } + + /** + * Print an object. + * + * @param object + */ + public void print(Object object) { + Set objects = new HashSet(); + print(object, objects); + } + + /** + * Print an object. + * + * @param object + */ + private void print(Object object, Set printed) { + if (object == null) { + return; + } + int id = System.identityHashCode(object); + if (printed.contains(id)) { + + // If we've already printed an object, print just it's HashCode + indent(); + out.println(object.getClass().getName() + "@" + id); + } else { + printed.add(id); + try { + + // Print the object class name + indent(); + out.println(object.getClass().getSimpleName() + " {"); + + // Get the object's properties + ValueAccessor accessor = useGetters ? new PropertyAccessor(object) : new FieldAccessor(object); + for (int i = 0; i < accessor.size(); i++) { + try { + + // Get the value of each property + Object value = accessor.getValue(i); + if (value != null) { + + // Convert array value into a list + if (value.getClass().isArray()) { + value = Arrays.asList((Object[])value); + } + + // Print elements in a list + if (value instanceof List) { + if (!((List)value).isEmpty()) { + indent++; + indent(); + out.println(accessor.getName(i) + "= ["); + + // Print each element, recursively + for (Object element : (List)value) { + indent++; + print(element, printed); + indent--; + } + indent(); + out.println(" ]"); + indent--; + } + } else { + Class valueClass = value.getClass(); + + // Print a primitive, java built in type or + // enum, using toString() + if (valueClass.isPrimitive() || valueClass.getName().startsWith("java.") + || valueClass.getName().startsWith("javax.") + || valueClass.isEnum()) { + if (!accessor.getName(i).equals("class")) { + if (!(Boolean.FALSE.equals(value))) { + indent++; + indent(); + out.println(accessor.getName(i) + "=" + value.toString()); + indent--; + } + } + } else if (value instanceof Node) { + indent++; + indent(); + out.println(accessor.getName(i) + "=" + value.toString()); + indent--; + } else { + + // Print an object, recursively + indent++; + indent(); + out.println(accessor.getName(i) + "= {"); + indent++; + print(value, printed); + indent--; + indent(); + out.println("}"); + indent--; + } + } + } + } catch (Exception e) { + } + } + indent(); + out.println("}"); + } catch (Exception e) { + indent(); + out.println(e); + } + } + } + + public static interface ValueAccessor { + int size(); + + String getName(int i); + + Object getValue(int i) throws Exception; + } + + /** + * Java field reflection based value accessor + */ + private static class FieldAccessor implements ValueAccessor { + + private Object object; + private List fields; + + public FieldAccessor(Object object) { + this.fields = getAllFields(object.getClass()); + this.object = object; + } + + public String getName(int i) { + return fields.get(i).getName(); + } + + public Object getValue(int i) throws Exception { + return fields.get(i).get(object); + } + + public int size() { + return fields.size(); + } + + } + + /** + * JavaBean-based value accessor + */ + private static class PropertyAccessor implements ValueAccessor { + + private Object object; + private PropertyDescriptor[] fields; + + public PropertyAccessor(Object object) throws IntrospectionException { + BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass()); + this.fields = beanInfo.getPropertyDescriptors(); + this.object = object; + } + + public String getName(int i) { + return fields[i].getName(); + } + + public Object getValue(int i) throws Exception { + Method getter = fields[i].getReadMethod(); + if (getter != null) { + return getter.invoke(object); + } + return null; + } + + public int size() { + return fields.length; + } + + } + + /** + * Returns a collection of fields declared by a class + * or one of its supertypes + */ + private static List getAllFields(Class clazz) { + return getAllFields(clazz, new ArrayList()); + } + + /** + * Recursively evaluates the type hierarchy to return all fields + */ + private static List getAllFields(Class clazz, List fields) { + if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) { + return fields; + } + fields = getAllFields(clazz.getSuperclass(), fields); + Field[] declaredFields = clazz.getDeclaredFields(); + for (final Field field : declaredFields) { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + field.setAccessible(true); // ignore Java accessibility + return null; + } + }); + fields.add(field); + } + return fields; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java new file mode 100644 index 0000000000..32a39fbb5f --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ProblemImpl.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.builder.impl; + +import org.apache.tuscany.sca.assembly.builder.Problem; + +/** + * Reports a composite assembly problem. + * + * @version $Rev: 589508 $ $Date: 2007-10-28 23:23:26 -0700 (Sun, 28 Oct 2007) $ + */ +public class ProblemImpl implements Problem { + + private String message; + private Severity severity; + private Object model; + private Object resource; + private Exception cause; + + /** + * Constructs a new problem. + * + * @param severity + * @param message + * @param model + */ + public ProblemImpl(Severity severity, String message, Object model) { + this.severity = severity; + this.message = message; + this.model = model; + } + + /** + * Constructs a new problem. + * + * @param severity + * @param message + * @param model + * @param resource + */ + public ProblemImpl(Severity severity, String message, Object model, Object resource) { + this.severity = severity; + this.message = message; + this.model = model; + this.resource = resource; + } + + /** + * Constructs a new problem. + * + * @param severity + * @param message + * @param cause + */ + public ProblemImpl(Severity severity, String message, Exception cause) { + this.severity = severity; + this.message = message; + this.cause = cause; + } + + public Severity getSeverity() { + return severity; + } + + public String getMessage() { + return message; + } + + public Object getModel() { + return model; + } + + public Object getResource() { + return resource; + } + + public Exception getCause() { + return cause; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + if (message != null) { + sb.append(message); + } + if (resource != null) { + if (sb.length() != 0) { + sb.append(" - "); + } + sb.append(resource.toString()); + } + return sb.toString(); + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyUtil.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyUtil.java new file mode 100644 index 0000000000..396cf011aa --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/PropertyUtil.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.assembly.builder.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +/** + * Utility class to deal with processing of component properties that are taking values from the parent + * composite's properties or an external file. + */ +public class PropertyUtil { + //private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance(); + private static final DocumentBuilderFactory DOC_BUILDER_FACTORY = DocumentBuilderFactory.newInstance(); + //private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance(); + + static private Document evaluate(Document node, XPathExpression expression) + throws XPathExpressionException, ParserConfigurationException { + + Node value = node.getDocumentElement(); + Node result = (Node)expression.evaluate(value, XPathConstants.NODE); + if (result == null) { + return null; + } + + // TODO: How to wrap the result into a Document? + Document document = DOC_BUILDER_FACTORY.newDocumentBuilder().newDocument(); + if (result instanceof Document) { + return (Document)result; + } else { + //Element root = document.createElementNS(null, "value"); + //document.appendChild(root); + document.appendChild(document.importNode(result, true)); + return document; + } + } + + static private Document loadFromFile(String file) throws MalformedURLException, IOException, + TransformerException, ParserConfigurationException { + URI uri = URI.create(file); + // URI resolution for relative URIs is done when the composite is resolved. + URL url = uri.toURL(); + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + InputStream is = null; + try { + is = connection.getInputStream(); + + Source streamSource = new SAXSource(new InputSource(is)); + DOMResult result = new DOMResult(); + //javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer(); + //transformer.transform(streamSource, result); + throw new NotImplementedException(); + + //return (Document)result.getNode(); + } finally { + if (is != null) { + is.close(); + } + } + } + + static void sourceComponentProperties(Map compositeProperties, + Component componentDefinition) throws CompositeBuilderException, + ParserConfigurationException, + XPathExpressionException, + TransformerException, + IOException { + + List componentProperties = componentDefinition.getProperties(); + for (ComponentProperty aProperty : componentProperties) { + String source = aProperty.getSource(); + String file = aProperty.getFile(); + if (source != null) { + // $/... + int index = source.indexOf('/'); + if (index == -1) { + // Tolerating $prop + source = source + "/"; + index = source.length() - 1; + } + if (source.charAt(0) == '$') { + String name = source.substring(1, index); + Property compositeProp = compositeProperties.get(name); + if (compositeProp == null) { + throw new CompositeBuilderException("The 'source' cannot be resolved to a composite property: " + source); + } + + Document compositePropDefValues = (Document)compositeProp.getValue(); + + // FIXME: How to deal with namespaces? + Document node = evaluate(compositePropDefValues, aProperty.getSourceXPathExpression()); + + if (node != null) { + aProperty.setValue(node); + } + } else { + throw new CompositeBuilderException("The 'source' has an invalid value: " + source); + } + } else if (file != null) { + aProperty.setValue(loadFromFile(aProperty.getFile())); + + } + } + } + + private static class DOMNamespaceContext implements NamespaceContext { + private Node node; + + /** + * @param node + */ + public DOMNamespaceContext(Node node) { + super(); + this.node = node; + } + + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("Prefix is null"); + } else if (XMLConstants.XML_NS_PREFIX.equals(prefix)) { + return XMLConstants.XML_NS_URI; + } else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) { + return XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + } + String ns = node.lookupNamespaceURI(prefix); + return ns == null ? XMLConstants.NULL_NS_URI : ns; + } + + public String getPrefix(String namespaceURI) { + if (namespaceURI == null) { + throw new IllegalArgumentException("Namespace URI is null"); + } else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) { + return XMLConstants.XML_NS_PREFIX; + } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { + return XMLConstants.XMLNS_ATTRIBUTE; + } + return node.lookupPrefix(namespaceURI); + } + + public Iterator getPrefixes(String namespaceURI) { + // Not implemented + if (namespaceURI == null) { + throw new IllegalArgumentException("Namespace URI is null"); + } else if (XMLConstants.XML_NS_URI.equals(namespaceURI)) { + return Arrays.asList(XMLConstants.XML_NS_PREFIX).iterator(); + } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI)) { + return Arrays.asList(XMLConstants.XMLNS_ATTRIBUTE).iterator(); + } + String prefix = getPrefix(namespaceURI); + if (prefix == null) { + return Collections.emptyList().iterator(); + } + return Arrays.asList(prefix).iterator(); + } + + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceUtil.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceUtil.java new file mode 100644 index 0000000000..d2eeb51ee7 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/builder/impl/ReferenceUtil.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.builder.impl; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.OptimizableBinding; + +/** + * This class encapsulates utility methods to deal with reference definitions + * + */ +class ReferenceUtil { + static boolean isValidMultiplicityOverride(Multiplicity definedMul, Multiplicity overridenMul) { + if (definedMul != overridenMul) { + switch (definedMul) { + case ZERO_N: + return overridenMul == Multiplicity.ZERO_ONE; + case ONE_N: + return overridenMul == Multiplicity.ONE_ONE; + default: + return false; + } + } else { + return true; + } + } + + static boolean validateMultiplicityAndTargets(Multiplicity multiplicity, + List targets, List bindings) { + + // Count targets + int count = targets.size(); + + //FIXME workaround, this validation is sometimes invoked too early + // before we get a chance to init the multiplicity attribute + if (multiplicity == null) { + return true; + } + + switch (multiplicity) { + case ZERO_N: + break; + case ZERO_ONE: + if (count > 1) { + return false; + } + break; + case ONE_ONE: + if (count != 1) { + if (count == 0) { + for (Binding binding: bindings) { + if (!(binding instanceof OptimizableBinding) || binding.getURI()!=null) { + return true; + } + } + } + return false; + } + break; + case ONE_N: + if (count < 1) { + if (count == 0) { + for (Binding binding: bindings) { + if (!(binding instanceof OptimizableBinding) || binding.getURI()!=null) { + return true; + } + } + } + return false; + } + break; + } + return true; + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractPropertyImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractPropertyImpl.java new file mode 100644 index 0000000000..75cb91189b --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractPropertyImpl.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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AbstractProperty; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; + +/** + * Represents an abstract property. + * + * @version $Rev: 592745 $ $Date: 2007-11-07 05:36:22 -0800 (Wed, 07 Nov 2007) $ + */ +public class AbstractPropertyImpl extends ExtensibleImpl implements AbstractProperty { + private Object value; + private String name; + private QName xsdType; + private QName xsdElement; + private boolean many; + private boolean mustSupply; + private List requiredIntents = new ArrayList(); + + + public List getRequiredIntents() { + return requiredIntents; + } + + /** + * Constructs a new abstract property. + */ + protected AbstractPropertyImpl() { + } + + public Object getValue() { + return value; + } + + public String getName() { + return name; + } + + public QName getXSDElement() { + return xsdElement; + } + + public QName getXSDType() { + return xsdType; + } + + public boolean isMany() { + return many; + } + + public boolean isMustSupply() { + return mustSupply; + } + + public void setValue(Object defaultValue) { + this.value = defaultValue; + } + + public void setMany(boolean many) { + this.many = many; + } + + public void setMustSupply(boolean mustSupply) { + this.mustSupply = mustSupply; + } + + public void setName(String name) { + this.name = name; + } + + public void setXSDElement(QName element) { + this.xsdElement = element; + } + + public void setXSDType(QName type) { + this.xsdType = type; + } + + public IntentAttachPointType getType() { + return null; + } + + public void setType(IntentAttachPointType type) { + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractReferenceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractReferenceImpl.java new file mode 100644 index 0000000000..16dc8394ce --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractReferenceImpl.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.impl; + +import org.apache.tuscany.sca.assembly.AbstractReference; +import org.apache.tuscany.sca.assembly.Multiplicity; + +/** + * Represents an abstract reference + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public class AbstractReferenceImpl extends ContractImpl implements AbstractReference { + private Multiplicity multiplicity = Multiplicity.ONE_ONE; + + /** + * Constructs a new abstract reference. + */ + protected AbstractReferenceImpl() { + } + + public Multiplicity getMultiplicity() { + return multiplicity; + } + + public void setMultiplicity(Multiplicity multiplicity) { + this.multiplicity = multiplicity; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractServiceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractServiceImpl.java new file mode 100644 index 0000000000..ba58b50748 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AbstractServiceImpl.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.assembly.impl; + +import org.apache.tuscany.sca.assembly.AbstractService; + +/** + * Represents an abstract service + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public class AbstractServiceImpl extends ContractImpl implements AbstractService { + + /** + * Constructs a new abstract service. + */ + protected AbstractServiceImpl() { + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AssemblyFactoryImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AssemblyFactoryImpl.java new file mode 100644 index 0000000000..9214df05a9 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/AssemblyFactoryImpl.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.assembly.impl; + +import org.apache.tuscany.sca.assembly.AbstractProperty; +import org.apache.tuscany.sca.assembly.AbstractReference; +import org.apache.tuscany.sca.assembly.AbstractService; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Callback; +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.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.Wire; + +/** + * A factory for the assembly model. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public abstract class AssemblyFactoryImpl implements AssemblyFactory { + + public AbstractProperty createAbstractProperty() { + return new AbstractPropertyImpl(); + } + + public AbstractReference createAbstractReference() { + return new AbstractReferenceImpl(); + } + + public AbstractService createAbstractService() { + return new AbstractServiceImpl(); + } + + public Callback createCallback() { + return new CallbackImpl(); + } + + public Component createComponent() { + return new ComponentImpl(); + } + + public ComponentProperty createComponentProperty() { + return new ComponentPropertyImpl(); + } + + public ComponentReference createComponentReference() { + return new ComponentReferenceImpl(); + } + + public ComponentService createComponentService() { + return new ComponentServiceImpl(); + } + + public ComponentType createComponentType() { + return new ComponentTypeImpl(); + } + + public Composite createComposite() { + return new CompositeImpl(); + } + + public CompositeReference createCompositeReference() { + return new CompositeReferenceImpl(); + } + + public CompositeService createCompositeService() { + return new CompositeServiceImpl(); + } + + public ConstrainingType createConstrainingType() { + return new ConstrainingTypeImpl(); + } + + public Property createProperty() { + return new PropertyImpl(); + } + + public Reference createReference() { + return new ReferenceImpl(); + } + + public Service createService() { + return new ServiceImpl(); + } + + public Wire createWire() { + return new WireImpl(); + } + + public ConfiguredOperation createConfiguredOperation() { + return new ConfiguredOperationImpl(); + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/BaseImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/BaseImpl.java new file mode 100644 index 0000000000..f51162598b --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/BaseImpl.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.assembly.impl; + +import org.apache.tuscany.sca.assembly.Base; + +/** + * Convenience base class for assembly model objects. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public abstract class BaseImpl implements Base { + private boolean unresolved; + + /** + * Constructs a new base model object. + */ + protected BaseImpl() { + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean undefined) { + this.unresolved = undefined; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CallbackImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CallbackImpl.java new file mode 100644 index 0000000000..c8af31eee8 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CallbackImpl.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Callback; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a reference. + * + * @version $Rev: 620307 $ $Date: 2008-02-10 10:56:51 -0800 (Sun, 10 Feb 2008) $ + */ +public class CallbackImpl extends ExtensibleImpl implements Callback { + private List bindings = new ArrayList(); + private List requiredIntents = new ArrayList(); + private List policySets = new ArrayList(); + private List configuredOperations = new ArrayList(); + private List applicablePolicySets = new ArrayList(); + + public List getPolicySets() { + return policySets; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + protected CallbackImpl() { + } + + public List getBindings() { + return bindings; + } + + public IntentAttachPointType getType() { + return null; + } + + public void setType(IntentAttachPointType type) { + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } + + public List getConfiguredOperations() { + return configuredOperations; + } + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentImpl.java new file mode 100644 index 0000000000..e30ff1e725 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentImpl.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +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.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a component. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public class ComponentImpl extends ExtensibleImpl implements Component, Cloneable, OperationsConfigurator { + private ConstrainingType constrainingType; + private Implementation implementation; + private String name; + private String uri; + private List properties = new ArrayList(); + private List references = new ArrayList(); + private List services = new ArrayList(); + private List requiredIntents = new ArrayList(); + private List policySets = new ArrayList(); + private Boolean autowire; + private IntentAttachPointType type; + private List configuredImplOperations = new ArrayList(); + private List applicablePolicySets = new ArrayList(); + /** + * Constructs a new component. + */ + protected ComponentImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + ComponentImpl clone = (ComponentImpl)super.clone(); + + clone.properties = new ArrayList(); + for (ComponentProperty property : getProperties()) { + clone.properties.add((ComponentProperty)property.clone()); + } + clone.references = new ArrayList(); + for (ComponentReference reference : getReferences()) { + clone.references.add((ComponentReference)reference.clone()); + } + clone.services = new ArrayList(); + for (ComponentService service : getServices()) { + clone.services.add((ComponentService)service.clone()); + } + return clone; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public ConstrainingType getConstrainingType() { + return constrainingType; + } + + public Implementation getImplementation() { + return implementation; + } + + public String getName() { + return name; + } + + public List getProperties() { + return properties; + } + + public List getReferences() { + return references; + } + + public List getServices() { + return services; + } + + public void setConstrainingType(ConstrainingType constrainingType) { + this.constrainingType = constrainingType; + } + + public void setImplementation(Implementation implementation) { + this.implementation = implementation; + } + + public void setName(String name) { + this.name = name; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + public List getPolicySets() { + return policySets; + } + + public boolean isAutowire() { + return (autowire == null) ? false : autowire.booleanValue(); + } + + public void setAutowire(Boolean autowire) { + this.autowire = autowire; + } + + public Boolean getAutowire() { + return autowire; + } + + public IntentAttachPointType getType() { + return type; + } + + public void setType(IntentAttachPointType type) { + this.type = type; + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + + } + + public List getConfiguredOperations() { + return configuredImplOperations; + } + + public void setConfiguredOperations(List configuredOperations) { + this.configuredImplOperations = configuredOperations; + } + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentPropertyImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentPropertyImpl.java new file mode 100644 index 0000000000..e5aa4e2db7 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentPropertyImpl.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.assembly.impl; + +import javax.xml.xpath.XPathExpression; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; + +/** + * Represents a component property. + * + * @version $Rev: 636985 $ $Date: 2008-03-13 20:48:47 -0700 (Thu, 13 Mar 2008) $ + */ +public class ComponentPropertyImpl extends PropertyImpl implements ComponentProperty, Cloneable { + private String file; + private Property property; + private String source; + private XPathExpression sourceXPathExpression; + + /** + * Constructs a new component property. + */ + protected ComponentPropertyImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + // FIXME getValue should not delegate to property.getValue() + // Doing this violates the setValue/getValue semantics, as you + // can call setValue() then get a different value from getValue() + @Override + public Object getValue() { + if (super.getValue() == null && property != null) { + return property.getValue(); + } else { + return super.getValue(); + } + } + + public String getFile() { + return file; + } + + public Property getProperty() { + return property; + } + + public String getSource() { + return source; + } + + public void setFile(String file) { + this.file = file; + } + + public void setProperty(Property property) { + this.property = property; + } + + public void setSource(String source) { + this.source = source; + } + + public XPathExpression getSourceXPathExpression() { + return sourceXPathExpression; + } + + public void setSourceXPathExpression(XPathExpression sourceXPathExpression) { + this.sourceXPathExpression = sourceXPathExpression; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentReferenceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentReferenceImpl.java new file mode 100644 index 0000000000..799e1c2e23 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentReferenceImpl.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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +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.Reference; + +/** + * Represents a component reference + * + * @version $Rev: 571694 $ $Date: 2007-08-31 22:24:11 -0700 (Fri, 31 Aug 2007) $ + */ +public class ComponentReferenceImpl extends ReferenceImpl implements ComponentReference, Cloneable { + private Reference reference; + private Boolean autowire; + private List promotedAs = new ArrayList(); + private ComponentService callbackService; + + /** + * Constructs a new component reference. + */ + protected ComponentReferenceImpl() { + // Set multiplicity to null so that by default it'll inherit from the Reference + setMultiplicity(null); + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public Reference getReference() { + return reference; + } + + public void setReference(Reference reference) { + this.reference = reference; + } + + public boolean isAutowire() { + return (autowire == null) ? false : autowire.booleanValue(); + } + + public void setAutowire(Boolean autowire) { + this.autowire = autowire; + } + + public Boolean getAutowire() { + return autowire; + } + + public List promotedAs() { + return promotedAs; + } + + public ComponentService getCallbackService() { + return callbackService; + } + + public void setCallbackService(ComponentService callbackService) { + this.callbackService = callbackService; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentServiceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentServiceImpl.java new file mode 100644 index 0000000000..7432b655e9 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentServiceImpl.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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Service; + +/** + * Represents a component service + * + * @version $Rev: 564107 $ $Date: 2007-08-08 23:05:29 -0700 (Wed, 08 Aug 2007) $ + */ +public class ComponentServiceImpl extends ServiceImpl implements ComponentService, Cloneable { + private Service service; + private List promotedAs = new ArrayList(); + private ComponentReference callbackReference; + + /** + * Constructs a new component service. + */ + protected ComponentServiceImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public Service getService() { + return service; + } + + public void setService(Service service) { + this.service = service; + } + + public List promotedAs() { + return promotedAs; + } + + public ComponentReference getCallbackReference() { + return callbackReference; + } + + public void setCallbackReference(ComponentReference callbackReference) { + this.callbackReference = callbackReference; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentTypeImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentTypeImpl.java new file mode 100644 index 0000000000..a292857cd2 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ComponentTypeImpl.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; + +/** + * Represents a component type. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public class ComponentTypeImpl extends ExtensibleImpl implements ComponentType, Cloneable { + private String uri; + private ConstrainingType constrainingType; + private List properties = new ArrayList(); + private List references = new ArrayList(); + private List services = new ArrayList(); + /** + * Constructs a new component type. + */ + protected ComponentTypeImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + ComponentTypeImpl clone = (ComponentTypeImpl)super.clone(); + + clone.services = new ArrayList(); + for (Service service : getServices()) { + clone.services.add((Service)service.clone()); + } + clone.references = new ArrayList(); + for (Reference reference : getReferences()) { + clone.references.add((Reference)reference.clone()); + } + clone.properties = new ArrayList(); + for (Property property : getProperties()) { + clone.properties.add((Property)property.clone()); + } + return clone; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public ConstrainingType getConstrainingType() { + return constrainingType; + } + + public List getProperties() { + return properties; + } + + public List getReferences() { + return references; + } + + public List getServices() { + return services; + } + + public void setConstrainingType(ConstrainingType constrainingType) { + this.constrainingType = constrainingType; + } + + @Override + public int hashCode() { + return String.valueOf(getURI()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else { + if (obj instanceof ComponentType) { + if (getURI() != null) { + return getURI().equals(((ComponentType)obj).getURI()); + } else { + return ((ComponentType)obj).getURI() == null; + } + } else { + return false; + } + } + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeImpl.java new file mode 100644 index 0000000000..26829aa172 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeImpl.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.Wire; + +public class CompositeImpl extends ImplementationImpl implements Composite, Cloneable { + private List components = new ArrayList(); + private List includes = new ArrayList(); + private QName name; + private List wires = new ArrayList(); + private Boolean autowire; + private boolean local = true; + + /** + * Constructs a new composite. + */ + protected CompositeImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + CompositeImpl clone = (CompositeImpl)super.clone(); + + clone.components = new ArrayList(); + for (Component component : getComponents()) { + Component clonedComponent = (Component)component.clone(); + for (Service service : clone.getServices()) { + CompositeService compositeService = (CompositeService)service; + // Force the promoted component/service to be rebuilt against the clone + if (compositeService.getPromotedComponent() != null) { + compositeService.getPromotedComponent().setUnresolved(true); + } + if (compositeService.getPromotedService() != null) { + compositeService.getPromotedService().setUnresolved(true); + } + } + for (Reference reference : clone.getReferences()) { + CompositeReference compositeReference = (CompositeReference)reference; + for (ComponentReference ref : compositeReference.getPromotedReferences()) { + // Force the promoted reference to be rebuilt against the clone + ref.setUnresolved(true); + } + } + + clone.components.add(clonedComponent); + } + clone.wires = new ArrayList(); + for (Wire wire : getWires()) { + clone.wires.add((Wire)wire.clone()); + } + return clone; + } + + public List getComponents() { + return components; + } + + public List getIncludes() { + return includes; + } + + public QName getName() { + return name; + } + + public List getWires() { + return wires; + } + + public boolean isLocal() { + return local; + } + + public void setLocal(boolean local) { + this.local = local; + } + + public boolean isAutowire() { + return (autowire == null) ? false : autowire.booleanValue(); + } + + public void setAutowire(Boolean autowire) { + this.autowire = autowire; + } + + public Boolean getAutowire() { + return autowire; + } + + public void setName(QName name) { + this.name = name; + } + + @Override + public int hashCode() { + return String.valueOf(getName()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof Composite) { + if (getName() != null) { + return getName().equals(((Composite)obj).getName()); + } else { + return ((Composite)obj).getName() == null; + } + } else { + return false; + } + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeReferenceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeReferenceImpl.java new file mode 100644 index 0000000000..5d9c00ea82 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeReferenceImpl.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.CompositeReference; + +/** + * Represents a composite reference. + * + * @version $Rev: 537384 $ $Date: 2007-05-12 04:02:56 -0700 (Sat, 12 May 2007) $ + */ +public class CompositeReferenceImpl extends ReferenceImpl implements CompositeReference, Cloneable { + private List promotedReferences = new ArrayList(); + + /** + * Constructs a new composite reference. + */ + protected CompositeReferenceImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public List getPromotedReferences() { + return promotedReferences; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeServiceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeServiceImpl.java new file mode 100644 index 0000000000..ad91c5ffa4 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/CompositeServiceImpl.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.assembly.impl; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; + +/** + * Represents a composite service + * + * @version $Rev: 566036 $ $Date: 2007-08-14 23:16:47 -0700 (Tue, 14 Aug 2007) $ + */ +public class CompositeServiceImpl extends ServiceImpl implements CompositeService, Cloneable { + private ComponentService promotedService; + private Component promotedComponent; + + /** + * Constructs a new composite service. + */ + protected CompositeServiceImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public ComponentService getPromotedService() { + return promotedService; + } + + public void setPromotedService(ComponentService promotedService) { + this.promotedService = promotedService; + } + + public Component getPromotedComponent() { + return promotedComponent; + } + + public void setPromotedComponent(Component promotedComponent) { + this.promotedComponent = promotedComponent; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConfiguredOperationImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConfiguredOperationImpl.java new file mode 100644 index 0000000000..3bc3dfc6af --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConfiguredOperationImpl.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents an Operation. + */ +public class ConfiguredOperationImpl extends BaseImpl implements ConfiguredOperation { + private List policySets = new ArrayList(); + private List requiredIntents = new ArrayList(); + private List applicablePolicySets = new ArrayList(); + + private String name; + private String contractName; + + /** + * Constructs a new Operation. + */ + protected ConfiguredOperationImpl() { + } + + public List getPolicySets() { + return policySets; + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } + + public String getContractName() { + return contractName; + } + + public void setContractName(String contractName) { + this.contractName = contractName; + } + + public IntentAttachPointType getType() { + return null; + } + + public void setType(IntentAttachPointType type) { + } + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConstrainingTypeImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConstrainingTypeImpl.java new file mode 100644 index 0000000000..5cf062821a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ConstrainingTypeImpl.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AbstractProperty; +import org.apache.tuscany.sca.assembly.AbstractReference; +import org.apache.tuscany.sca.assembly.AbstractService; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; + +/** + * Represents a constraining type. + * + * @version $Rev: 592745 $ $Date: 2007-11-07 05:36:22 -0800 (Wed, 07 Nov 2007) $ + */ +public class ConstrainingTypeImpl extends ExtensibleImpl implements ConstrainingType { + private QName name; + private List properties = new ArrayList(); + private List references = new ArrayList(); + private List services = new ArrayList(); + private List requiredIntents = new ArrayList(); + + /** + * Constructs a new ConstrainingType + */ + protected ConstrainingTypeImpl() { + } + + public QName getName() { + return name; + } + + public void setName(QName name) { + this.name = name; + } + + public List getProperties() { + return properties; + } + + public List getReferences() { + return references; + } + + public List getServices() { + return services; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + @Override + public int hashCode() { + return String.valueOf(getName()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof ConstrainingType) { + if (getName() != null) { + return getName().equals(((ConstrainingType)obj).getName()); + } else { + return ((ConstrainingType)obj).getName() == null; + } + } else { + return false; + } + } + + public IntentAttachPointType getType() { + return null; + } + + public void setType(IntentAttachPointType type) { + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ContractImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ContractImpl.java new file mode 100644 index 0000000000..874efe45da --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ContractImpl.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AbstractContract; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; + +public class ContractImpl extends ExtensibleImpl implements AbstractContract { + private InterfaceContract interfaceContract; + private String name; + private List requiredIntents = new ArrayList(); + private List configuredOperations = new ArrayList(); + + private boolean isCallback = false; + + /** + * Constructs a new contract. + */ + protected ContractImpl() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public InterfaceContract getInterfaceContract() { + return interfaceContract; + } + + public void setInterfaceContract(InterfaceContract interfaceContract) { + this.interfaceContract = interfaceContract; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + public boolean isCallback() { + return isCallback; + } + + public void setIsCallback(boolean isCallback) { + this.isCallback = isCallback; + } + + public IntentAttachPointType getType() { + return null; + } + + public void setType(IntentAttachPointType type) { + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } + + public List getConfiguredOperations() { + return configuredOperations; + } + + public void setConfiguredOperations(List configuredOperations) { + this.configuredOperations = configuredOperations; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ExtensibleImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ExtensibleImpl.java new file mode 100644 index 0000000000..38b6cd7ce3 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ExtensibleImpl.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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Extensible; + +/** + * Convenience base class for extensible assembly model objects. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public abstract class ExtensibleImpl extends BaseImpl implements Extensible { + private List extensions = new ArrayList(); + + /** + * Constructs a new base model object. + */ + protected ExtensibleImpl() { + } + + public List getExtensions() { + return extensions; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ImplementationImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ImplementationImpl.java new file mode 100644 index 0000000000..81bed59e1a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ImplementationImpl.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.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Base implementation class of Implementation model interface + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public abstract class ImplementationImpl extends ComponentTypeImpl implements Implementation, PolicySetAttachPoint, + OperationsConfigurator { + + private List applicablePolicySets = new ArrayList(); + private List configuredOperations = new ArrayList(); + private IntentAttachPointType type; + private List policySets = new ArrayList(); + private List requiredIntents = new ArrayList(); + + protected ImplementationImpl() { + super(); + } + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + + public List getConfiguredOperations() { + return configuredOperations; + } + + public List getPolicySets() { + return policySets; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + public IntentAttachPointType getType() { + return type; + } + + public void setType(IntentAttachPointType type) { + this.type = type; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/PropertyImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/PropertyImpl.java new file mode 100644 index 0000000000..73604736a5 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/PropertyImpl.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a property. + * + * @version $Rev: 620307 $ $Date: 2008-02-10 10:56:51 -0800 (Sun, 10 Feb 2008) $ + */ +public class PropertyImpl extends AbstractPropertyImpl implements Property, Cloneable { + private List policySets = new ArrayList(); + private List applicablePolicySets = new ArrayList(); + + /** + * Constructs a new property. + */ + protected PropertyImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public List getPolicySets() { + return policySets; + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + + public List getApplicablePolicySets() { + return applicablePolicySets; + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ReferenceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ReferenceImpl.java new file mode 100644 index 0000000000..186e98cd5e --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ReferenceImpl.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Callback; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a reference. + * + * @version $Rev: 620307 $ $Date: 2008-02-10 10:56:51 -0800 (Sun, 10 Feb 2008) $ + */ +public class ReferenceImpl extends AbstractReferenceImpl implements Reference, Cloneable { + private List bindings = new ArrayList(); + private boolean wiredByImpl; + private List policySets = new ArrayList(); + private List targets = new ArrayList(); + private Callback callback; + private List applicablePolicySets = new ArrayList(); + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + + /** + * Constructs a new reference. + */ + protected ReferenceImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + ReferenceImpl clone = (ReferenceImpl)super.clone(); + clone.bindings = new ArrayList(); + clone.bindings.addAll(getBindings()); + clone.targets = new ArrayList(); + clone.targets.addAll(getTargets()); + return clone; + } + + public List getBindings() { + return bindings; + } + + public B getBinding(Class bindingClass) { + for (Binding binding : bindings) { + if (bindingClass.isInstance(binding)) { + return bindingClass.cast(binding); + } + } + return null; + } + + public B getCallbackBinding(Class bindingClass) { + if (callback != null) { + for (Binding binding : callback.getBindings()) { + if (bindingClass.isInstance(binding)) { + return bindingClass.cast(binding); + } + } + } + return null; + } + + public boolean isWiredByImpl() { + return wiredByImpl; + } + + public void setWiredByImpl(boolean wiredByImpl) { + this.wiredByImpl = wiredByImpl; + } + + public List getPolicySets() { + return policySets; + } + + public List getTargets() { + return targets; + } + + public Callback getCallback() { + return callback; + } + + public void setCallback(Callback callback) { + this.callback = callback; + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ServiceImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ServiceImpl.java new file mode 100644 index 0000000000..b01bd42a96 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/ServiceImpl.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Callback; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a reference. + * + * @version $Rev: 620307 $ $Date: 2008-02-10 10:56:51 -0800 (Sun, 10 Feb 2008) $ + */ +public class ServiceImpl extends AbstractServiceImpl implements Service, Cloneable { + private List bindings = new ArrayList(); + private List policySets = new ArrayList(); + private Callback callback; + private List applicablePolicySets = new ArrayList(); + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + + /** + * Constructs a new service. + */ + protected ServiceImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + ServiceImpl clone = (ServiceImpl)super.clone(); + clone.bindings = new ArrayList(); + clone.bindings.addAll(getBindings()); + return clone; + } + + public List getBindings() { + return bindings; + } + + public B getBinding(Class bindingClass) { + for (Binding binding : bindings) { + if (bindingClass.isInstance(binding)) { + return bindingClass.cast(binding); + } + } + return null; + } + + public B getCallbackBinding(Class bindingClass) { + if (callback != null) { + for (Binding binding : callback.getBindings()) { + if (bindingClass.isInstance(binding)) { + return bindingClass.cast(binding); + } + } + } + return null; + } + + public List getPolicySets() { + return policySets; + } + + public Callback getCallback() { + return callback; + } + + public void setCallback(Callback callback) { + this.callback = callback; + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/WireImpl.java b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/WireImpl.java new file mode 100644 index 0000000000..2c8f426f82 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/main/java/org/apache/tuscany/sca/assembly/impl/WireImpl.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Wire; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a wire + * + * @version $Rev: 620307 $ $Date: 2008-02-10 10:56:51 -0800 (Sun, 10 Feb 2008) $ + */ +public class WireImpl extends ExtensibleImpl implements Wire, Cloneable { + private ComponentReference source; + private ComponentService target; + private List requiredIntents = new ArrayList(); + private List policySets = new ArrayList(); + private List applicablePolicySets = new ArrayList(); + + public List getApplicablePolicySets() { + return applicablePolicySets; + } + + /** + * Constructs a new wire. + */ + protected WireImpl() { + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public ComponentReference getSource() { + return source; + } + + public ComponentService getTarget() { + return target; + } + + public void setSource(ComponentReference source) { + this.source = source; + } + + public void setTarget(ComponentService target) { + this.target = target; + } + + public List getRequiredIntents() { + return requiredIntents; + } + + public List getPolicySets() { + return policySets; + } + + public IntentAttachPointType getType() { + return null; + } + + public void setType(IntentAttachPointType type) { + } + + public void setPolicySets(List policySets) { + this.policySets = policySets; + } + + public void setRequiredIntents(List intents) { + this.requiredIntents = intents; + } +} diff --git a/branches/sca-android/tuscany-assembly/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory b/branches/sca-android/tuscany-assembly/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory new file mode 100644 index 0000000000..859c4bde4b --- /dev/null +++ b/branches/sca-android/tuscany-assembly/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. + +org.apache.tuscany.sca.assembly.DefaultAssemblyFactory \ No newline at end of file diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/AssemblyFactoryTestCase.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/AssemblyFactoryTestCase.java new file mode 100644 index 0000000000..2c8bf309df --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/AssemblyFactoryTestCase.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + + +/** + * Test building of assembly model instances using the assembly factory. + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class AssemblyFactoryTestCase extends TestCase { + + AssemblyFactory factory; + + @Override + public void setUp() throws Exception { + factory = new DefaultAssemblyFactory(); + } + + @Override + public void tearDown() throws Exception { + factory = null; + } + + public void testCreateComponent() { + createComponent("AccountServiceComponent1"); + } + + public void testCreateComponentType() { + createComponentType(); + } + + public void testCreateComposite() { + createComposite(); + } + + public void testCreateConstrainingType() { + createConstrainingType(); + } + + /** + * Create a composite + */ + Composite createComposite() { + Composite c = factory.createComposite(); + + Component c1 = createComponent("AccountServiceComponent1"); + c.getComponents().add(c1); + Component c2 = createComponent("AccountServiceComponent2"); + c.getComponents().add(c2); + + Wire w = factory.createWire(); + w.setSource(c1.getReferences().get(0)); + w.setTarget(c2.getServices().get(0)); + c.getWires().add(w); + + CompositeService cs = factory.createCompositeService(); + cs.setName("AccountService"); + cs.setPromotedService(c1.getServices().get(0)); + cs.setInterfaceContract(new TestInterfaceContract(factory)); + c.getServices().add(cs); + cs.getBindings().add(new TestBinding(factory)); + + CompositeReference cr = factory.createCompositeReference(); + cr.setName("StockQuoteService"); + cr.getPromotedReferences().add(c2.getReferences().get(1)); + cr.setInterfaceContract(new TestInterfaceContract(factory)); + c.getReferences().add(cr); + cr.getBindings().add(new TestBinding(factory)); + + return c; + } + + /** + * Create a new component + */ + Component createComponent(String name) { + Component c = factory.createComponent(); + c.setName(name); + + ConstrainingType constraint = createConstrainingType(); + c.setConstrainingType(constraint); + + Implementation i = new TestImplementation(factory); + c.setImplementation(i); + + ComponentProperty p = factory.createComponentProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + p.setProperty(i.getProperties().get(0)); + c.getProperties().add(p); + + ComponentReference ref1 = factory.createComponentReference(); + ref1.setName("accountDataService"); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + ref1.setInterfaceContract(new TestInterfaceContract(factory)); + ref1.setReference(i.getReferences().get(0)); + c.getReferences().add(ref1); + ref1.getBindings().add(new TestBinding(factory)); + + ComponentReference ref2 = factory.createComponentReference(); + ref2.setName("stockQuoteService"); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + ref2.setReference(i.getReferences().get(1)); + c.getReferences().add(ref2); + ref2.getBindings().add(new TestBinding(factory)); + + ComponentService s = factory.createComponentService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + s.setService(i.getServices().get(0)); + c.getServices().add(s); + s.getBindings().add(new TestBinding(factory)); + + return c; + } + + /** + * Create a new component type + * + * @return + */ + ComponentType createComponentType() { + ComponentType ctype = factory.createComponentType(); + + Property p = factory.createProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + ctype.getProperties().add(p); + + Reference ref1 = factory.createReference(); + ref1.setName("accountDataService"); + ref1.setInterfaceContract(new TestInterfaceContract(factory)); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref1); + ref1.getBindings().add(new TestBinding(factory)); + + Reference ref2 = factory.createReference(); + ref2.setName("stockQuoteService"); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref2); + ref2.getBindings().add(new TestBinding(factory)); + + Service s = factory.createService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + ctype.getServices().add(s); + s.getBindings().add(new TestBinding(factory)); + + return ctype; + } + + /** + * Create a new constraining type + * + * @return + */ + ConstrainingType createConstrainingType() { + ConstrainingType ctype = factory.createConstrainingType(); + + AbstractProperty p = factory.createAbstractProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + ctype.getProperties().add(p); + + AbstractReference ref1 = factory.createAbstractReference(); + ref1.setName("accountDataService"); + ref1.setInterfaceContract(new TestInterfaceContract(factory)); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref1); + + AbstractReference ref2 = factory.createAbstractReference(); + ref2.setName("stockQuoteService"); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref2); + + AbstractService s = factory.createAbstractService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + ctype.getServices().add(s); + + return ctype; + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestBinding.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestBinding.java new file mode 100644 index 0000000000..a6b594f311 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestBinding.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.assembly; + + +/** + * A test interface model. + * + * @version $Rev: 604880 $ $Date: 2007-12-17 06:30:07 -0800 (Mon, 17 Dec 2007) $ + */ +public class TestBinding implements Binding { + public TestBinding(AssemblyFactory factory) { + } + + public String getName() { + return null; + } + + public String getURI() { + return "http://test"; + } + + public void setName(String name) { + } + + public void setURI(String uri) { + } + + public void setUnresolved(boolean unresolved) { + } + + public boolean isUnresolved() { + return false; + } + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestImplementation.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestImplementation.java new file mode 100644 index 0000000000..698623ee1a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestImplementation.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.assembly; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.impl.ImplementationImpl; + +/** + * A test component implementation model. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +public class TestImplementation extends ImplementationImpl implements Implementation { + public TestImplementation(AssemblyFactory factory) { + + Property p = factory.createProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + getProperties().add(p); + + Reference ref1 = factory.createReference(); + ref1.setName("accountDataService"); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + getReferences().add(ref1); + ref1.getBindings().add(new TestBinding(factory)); + + Reference ref2 = factory.createReference(); + ref2.setName("stockQuoteService"); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + getReferences().add(ref2); + ref2.getBindings().add(new TestBinding(factory)); + + Service s = factory.createService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + getServices().add(s); + s.getBindings().add(new TestBinding(factory)); + + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterface.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterface.java new file mode 100644 index 0000000000..8e82efd04b --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterface.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl; + +/** + * A test interface model. + * + * @version $Rev: 537744 $ $Date: 2007-05-14 01:00:18 -0700 (Mon, 14 May 2007) $ + */ +public class TestInterface extends InterfaceImpl implements Interface { + + public TestInterface(AssemblyFactory factory) { + + setRemotable(true); + + Operation operation = new TestOperation(); + operation.setName("test"); + getOperations().add(operation); + + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterfaceContract.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterfaceContract.java new file mode 100644 index 0000000000..e020bdbc9a --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestInterfaceContract.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractImpl; + +/** + * A test interface contract model. + * + * @version $Rev: 537744 $ $Date: 2007-05-14 01:00:18 -0700 (Mon, 14 May 2007) $ + */ +public class TestInterfaceContract extends InterfaceContractImpl implements InterfaceContract { + + public TestInterfaceContract(AssemblyFactory factory) { + + TestInterface testInterface = new TestInterface(factory); + setInterface(testInterface); + + TestInterface testCallbackInterface = new TestInterface(factory); + setCallbackInterface(testCallbackInterface); + + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestOperation.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestOperation.java new file mode 100644 index 0000000000..996eb40b75 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/TestOperation.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.assembly; + +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; + +/** + * A test operation model. + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class TestOperation extends OperationImpl { + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CalculateBindingURITestCase.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CalculateBindingURITestCase.java new file mode 100644 index 0000000000..609e1733aa --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CalculateBindingURITestCase.java @@ -0,0 +1,554 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +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.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderMonitor; +import org.apache.tuscany.sca.assembly.builder.Problem; +import org.apache.tuscany.sca.assembly.builder.Problem.Severity; + +public class CalculateBindingURITestCase extends TestCase { + private final static Logger logger = Logger.getLogger(CalculateBindingURITestCase.class.getName()); + private AssemblyFactory assemblyFactory; + private SCABindingFactory scaBindingFactory = null; + private CompositeBuilderMonitor monitor = null; + private CompositeConfigurationBuilderImpl configurationBuilder = null; + private List defaultBindings = new ArrayList(); + + @Override + protected void setUp() throws Exception { + assemblyFactory = new DefaultAssemblyFactory(); + scaBindingFactory = new TestBindingFactory(); + monitor = new CompositeBuilderMonitor() { + public void problem(Problem problem) { + if (problem.getSeverity() == Severity.INFO) { + logger.info(problem.toString()); + } else if (problem.getSeverity() == Severity.WARNING) { + logger.warning(problem.toString()); + } else if (problem.getSeverity() == Severity.ERROR) { + if (problem.getCause() != null) { + logger.log(Level.SEVERE, problem.toString(), problem.getCause()); + } else { + logger.severe(problem.toString()); + } + } + } + }; + configurationBuilder = new CompositeConfigurationBuilderImpl(assemblyFactory, scaBindingFactory, null, null, monitor); + Binding defaultBinding = new TestBindingImpl(); + defaultBinding.setURI("http://myhost:8080/root"); + defaultBindings.add(defaultBinding); + } + + @Override + protected void tearDown() throws Exception { + assemblyFactory = null; + } + + /** + * Test that URI are generated in accordance with the Assembly Specification section 1.7.2.1 as + * follows. For the 3 parts that make up the URI; + * + * BaseURI / Component URI / Service Binding URI + * + * Test the following combinations for: + * + * NB. The short hand here, e.g. means + * two services appear where the first has the sca binding specified. + * + * component service bindings + * + * http://myhost:8080/root / / + * --> http://myhost:8080/root/c1 + * http://myhost:8080/root / / + * --> http://myhost:8080/root/c1/s1 + * http://myhost:8080/root / / + * --> http://myhost:8080/root/c1/n + * http://myhost:8080/root / / + * --> http://myhost:8080/root/c1/b + * http://myhost:8080/root / / + * --> http://myhost:8080/b + * http://myhost:8080/root / / + * --> http://myhost:8080/b + * + * top level composite service bindings + * + * http://myhost:8080/root / null / + * --> http://myhost:8080/root + * http://myhost:8080/root / null / + * --> http://myhost:8080/root/s1 + * http://myhost:8080/root / null / + * --> http://myhost:8080/root/n + * http://myhost:8080/root / null / + * --> http://myhost:8080/root/b + * http://myhost:8080/root / null / + * --> http://myhost:8080/b + * + * nested composite service bindings + * + * http://myhost:8080/root / implemented by composite with / + * --> http://myhost:8080/root/c1/c2 + * http://myhost:8080/root / implemented by composite with / + * --> http://myhost:8080/root/c1/c2/s1 + * http://myhost:8080/root / implemented by composite with / + * --> http://myhost:8080/root/c1/c2/n + * http://myhost:8080/root / implemented by composite with / + * --> http://myhost:8080/root/c1/c2/b + * http://myhost:8080/root / implemented by composite with / + * --> http://myhost:8080/b + * + * binding name duplication errors + * + * http://myhost:8080/root / implemented by composite with / + * --> Error + * http://myhost:8080/root / implemented by composite with / + * --> Error + */ + + private Composite createComponentServiceBinding() { + Composite composite1 = assemblyFactory.createComposite(); + composite1.setName(new QName("http://foo", "C1")); + + Component c1 = assemblyFactory.createComponent(); + c1.setName("c1"); + composite1.getComponents().add(c1); + + ComponentService s1 = assemblyFactory.createComponentService(); + c1.getServices().add(s1); + s1.setName("s1"); + + ComponentService s2 = assemblyFactory.createComponentService(); + c1.getServices().add(s2); + s2.setName("s2"); + + Binding b1 = new TestBindingImpl(); + s1.getBindings().add(b1); + + Binding b2 = new TestBindingImpl(); + s2.getBindings().add(b2); + + return composite1; + } + + private Composite createTopLevelCompositeServiceBinding(){ + Composite composite1 = assemblyFactory.createComposite(); + composite1.setName(new QName("http://foo", "C1")); + + CompositeService s1 = assemblyFactory.createCompositeService(); + s1.setName("s1"); + composite1.getServices().add(s1); + + Binding b1 = new TestBindingImpl(); + s1.getBindings().add(b1); + + CompositeService s2 = assemblyFactory.createCompositeService(); + s2.setName("s2"); + composite1.getServices().add(s2); + + Binding b2 = new TestBindingImpl(); + s2.getBindings().add(b2); + + return composite1; + } + + private Composite createNestCompositeServiceBinding(){ + Composite composite1 = assemblyFactory.createComposite(); + composite1.setName(new QName("http://foo", "C1")); + + Component c1 = assemblyFactory.createComponent(); + c1.setName("c1"); + composite1.getComponents().add(c1); + + Composite composite2 = assemblyFactory.createComposite(); + c1.setImplementation(composite2); + composite2.setName(new QName("http://foo", "C2")); + + Component c2 = assemblyFactory.createComponent(); + composite2.getComponents().add(c2); + c2.setName("c2"); + + ComponentService s1 = assemblyFactory.createComponentService(); + c2.getServices().add(s1); + s1.setName("s1"); + + ComponentService s2 = assemblyFactory.createComponentService(); + c2.getServices().add(s2); + s2.setName("s2"); + + Binding b1 = new TestBindingImpl(); + s1.getBindings().add(b1); + + Binding b2 = new TestBindingImpl(); + s2.getBindings().add(b2); + + return composite1; + } + + // component service binding tests + + public void testComponentServiceSingleService() { + Composite composite = createComponentServiceBinding(); + composite.getComponents().get(0).getServices().remove(1); + Binding b = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testComponentServiceBindingDefault() { + Composite composite = createComponentServiceBinding(); + Binding b = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/s1", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testComponentServiceBindingName() { + Composite composite = createComponentServiceBinding(); + Binding b = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/n", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testComponentServiceBindingURIRelative() { + Composite composite = createComponentServiceBinding(); + Binding b = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testComponentServiceBindingURIAbsolute() { + Composite composite = createComponentServiceBinding(); + Binding b = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("http://myhost:8080/b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testComponentServiceBindingURIRelative2() { + Composite composite = createComponentServiceBinding(); + Binding b = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("../../b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + // top level composite service binding tests + + public void testCompositeServiceSingleService() { + Composite composite = createTopLevelCompositeServiceBinding(); + composite.getServices().remove(1); + Binding b = composite.getServices().get(0).getBindings().get(0); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testCompositeServiceBindingDefault() { + Composite composite = createTopLevelCompositeServiceBinding(); + Binding b = composite.getServices().get(0).getBindings().get(0); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/s1", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testCompositeServiceBindingName() { + Composite composite = createTopLevelCompositeServiceBinding(); + Binding b = composite.getServices().get(0).getBindings().get(0); + b.setName("n"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/n", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testCompositeServiceBindingURIRelative() { + Composite composite = createTopLevelCompositeServiceBinding(); + Binding b = composite.getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testCompositeServiceBindingURIAbsolute() { + Composite composite = createTopLevelCompositeServiceBinding(); + Binding b = composite.getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("http://myhost:8080/b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + // nested composite service binding tests + + public void testNestedCompositeServiceSingleService() { + Composite composite = createNestCompositeServiceBinding(); + ((Composite)composite.getComponents().get(0).getImplementation()).getComponents().get(0).getServices().remove(1); + Binding b = ((Composite)composite.getComponents().get(0).getImplementation()).getComponents().get(0).getServices().get(0).getBindings().get(0); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/c2", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testNestedCompositeServiceBindingDefault() { + Composite composite = createNestCompositeServiceBinding(); + Binding b = ((Composite)composite.getComponents().get(0).getImplementation()).getComponents().get(0).getServices().get(0).getBindings().get(0); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/c2/s1", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testNestedCompositeServiceBindingName() { + Composite composite = createNestCompositeServiceBinding(); + Binding b = ((Composite)composite.getComponents().get(0).getImplementation()).getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/c2/n", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testNestedCompositeServiceBindingURIRelative() { + Composite composite = createNestCompositeServiceBinding(); + Binding b = ((Composite)composite.getComponents().get(0).getImplementation()).getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/root/c1/c2/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + public void testNestedCompositeServiceBindingURIAbsolute() { + Composite composite = createNestCompositeServiceBinding(); + Binding b = ((Composite)composite.getComponents().get(0).getImplementation()).getComponents().get(0).getServices().get(0).getBindings().get(0); + b.setName("n"); + b.setURI("http://myhost:8080/b"); + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + + assertEquals("http://myhost:8080/b", b.getURI()); + } catch(Exception ex){ + System.out.println(ex.toString()); + fail(); + } + } + + // component service binding name error tests + + //FIXME Need to find a better way to test these error cases as + // the composite builder now (intentionally) logs warnings instead of + // throwing exceptions + public void FIXMEtestComponentServiceBindingNameError1() { + Composite composite = createComponentServiceBinding(); + Binding b1 = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + Binding b2 = new TestBindingImpl(); + composite.getComponents().get(0).getServices().get(0).getBindings().add(b2); + + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + fail(); + } catch(Exception ex){ + //System.out.println(ex.toString()); + } + } + + //FIXME Need to find a better way to test these error cases as + // the composite builder now (intentionally) logs warnings instead of + // throwing exceptions + public void FIXMEtestComponentServiceBindingNameError2() { + Composite composite = createComponentServiceBinding(); + Binding b1 = composite.getComponents().get(0).getServices().get(0).getBindings().get(0); + Binding b2 = new TestBindingImpl(); + composite.getComponents().get(0).getServices().get(0).getBindings().add(b2); + + b1.setName("b"); + b2.setName("b"); + + + try { + configurationBuilder.configureBindingURIs(composite, null, defaultBindings); + fail(); + } catch(Exception ex){ + System.out.println(ex.toString()); + } + } + + + public class TestBindingFactory implements SCABindingFactory { + public SCABinding createSCABinding() { + return new TestBindingImpl(); + } + } + + public class TestBindingImpl implements SCABinding { + private String name; + private String uri; + private boolean unresolved; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public void setUnresolved(boolean unresolved) { + this.unresolved = unresolved; + } + + public boolean isUnresolved() { + return false; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderTestCase.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderTestCase.java new file mode 100644 index 0000000000..bef6b47ee7 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/CompositeBuilderTestCase.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; + +public class CompositeBuilderTestCase extends TestCase { + + private AssemblyFactory assemblyFactory; + + @Override + protected void setUp() throws Exception { + assemblyFactory = new DefaultAssemblyFactory(); + } + + @Override + protected void tearDown() throws Exception { + assemblyFactory = null; + } + + public void testFuseIncludes() { + Composite c1 = assemblyFactory.createComposite(); + c1.setName(new QName("http://foo", "C1")); + Component a = assemblyFactory.createComponent(); + a.setName("a"); + c1.getComponents().add(a); + CompositeService s = assemblyFactory.createCompositeService(); + s.setName("s"); + c1.getServices().add(s); + CompositeReference r = assemblyFactory.createCompositeReference(); + r.setName("r"); + c1.getReferences().add(r); + + Composite c2 = assemblyFactory.createComposite(); + c2.setName(new QName("http://foo", "C2")); + c1.getIncludes().add(c2); + Component b = assemblyFactory.createComponent(); + b.setName("b"); + c2.getComponents().add(b); + + Composite c = assemblyFactory.createComposite(); + c.setName(new QName("http://foo", "C")); + c.getIncludes().add(c1); + + new CompositeIncludeBuilderImpl(null).fuseIncludes(c); + + assertTrue(c.getComponents().get(0).getName().equals("a")); + assertTrue(c.getComponents().get(1).getName().equals("b")); + assertTrue(c.getServices().get(0).getName().equals("s")); + assertTrue(c.getReferences().get(0).getName().equals("r")); + } + + public void testExpandComposites() { + Composite c1 = assemblyFactory.createComposite(); + c1.setName(new QName("http://foo", "C1")); + Component a = assemblyFactory.createComponent(); + a.setName("a"); + c1.getComponents().add(a); + CompositeService s = assemblyFactory.createCompositeService(); + s.setName("s"); + c1.getServices().add(s); + CompositeReference r = assemblyFactory.createCompositeReference(); + r.setName("r"); + c1.getReferences().add(r); + + Composite c2 = assemblyFactory.createComposite(); + c2.setName(new QName("http://foo", "C2")); + Component b = assemblyFactory.createComponent(); + b.setName("b"); + c2.getComponents().add(b); + + Composite c = assemblyFactory.createComposite(); + c.setName(new QName("http://foo", "C")); + Component x = assemblyFactory.createComponent(); + x.setName("x"); + x.setImplementation(c1); + c.getComponents().add(x); + Component y = assemblyFactory.createComponent(); + y.setName("y"); + y.setImplementation(c2); + c.getComponents().add(y); + Component z = assemblyFactory.createComponent(); + z.setName("z"); + z.setImplementation(c1); + c.getComponents().add(z); + + new CompositeCloneBuilderImpl(null).expandCompositeImplementations(c); + + assertTrue(c.getComponents().get(0).getImplementation() != c1); + assertTrue(c.getComponents().get(1).getImplementation() != c2); + assertTrue(c.getComponents().get(2).getImplementation() != c1); + + Composite i = (Composite)c.getComponents().get(0).getImplementation(); + assertTrue(i.getComponents().get(0) != a); + assertTrue(i.getComponents().get(0).getName().equals("a")); + assertTrue(i.getServices().get(0).getName().equals("s")); + assertTrue(i.getServices().get(0) != s); + assertTrue(i.getReferences().get(0).getName().equals("r")); + assertTrue(i.getReferences().get(0) != r); + } + +} diff --git a/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtilTestCase.java b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtilTestCase.java new file mode 100644 index 0000000000..b87ffc5905 --- /dev/null +++ b/branches/sca-android/tuscany-assembly/src/test/java/org/apache/tuscany/sca/assembly/builder/impl/PrintUtilTestCase.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.assembly.builder.impl; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AbstractProperty; +import org.apache.tuscany.sca.assembly.AbstractReference; +import org.apache.tuscany.sca.assembly.AbstractService; +import org.apache.tuscany.sca.assembly.AssemblyFactory; +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.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.TestBinding; +import org.apache.tuscany.sca.assembly.TestImplementation; +import org.apache.tuscany.sca.assembly.TestInterfaceContract; +import org.apache.tuscany.sca.assembly.Wire; +import org.junit.Test; + +/** + * @version $Rev: 579601 $ $Date: 2007-09-26 04:25:30 -0700 (Wed, 26 Sep 2007) $ + */ +public class PrintUtilTestCase { + + private AssemblyFactory factory = new DefaultAssemblyFactory(); + + /** + * Create a composite + */ + Composite createComposite() { + Composite c = factory.createComposite(); + + Component c1 = createComponent("AccountServiceComponent1"); + c.getComponents().add(c1); + Component c2 = createComponent("AccountServiceComponent2"); + c.getComponents().add(c2); + + Wire w = factory.createWire(); + w.setSource(c1.getReferences().get(0)); + w.setTarget(c2.getServices().get(0)); + c.getWires().add(w); + + CompositeService cs = factory.createCompositeService(); + cs.setName("AccountService"); + cs.setPromotedService(c1.getServices().get(0)); + cs.setInterfaceContract(new TestInterfaceContract(factory)); + c.getServices().add(cs); + cs.getBindings().add(new TestBinding(factory)); + + CompositeReference cr = factory.createCompositeReference(); + cr.setName("StockQuoteService"); + cr.getPromotedReferences().add(c2.getReferences().get(1)); + cr.setInterfaceContract(new TestInterfaceContract(factory)); + c.getReferences().add(cr); + cr.getBindings().add(new TestBinding(factory)); + + return c; + } + + /** + * Create a new component + */ + Component createComponent(String name) { + Component c = factory.createComponent(); + c.setName(name); + + ConstrainingType constraint = createConstrainingType(); + c.setConstrainingType(constraint); + + Implementation i = new TestImplementation(factory); + c.setImplementation(i); + + ComponentProperty p = factory.createComponentProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + p.setProperty(i.getProperties().get(0)); + c.getProperties().add(p); + + ComponentReference ref1 = factory.createComponentReference(); + ref1.setName("accountDataService"); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + ref1.setInterfaceContract(new TestInterfaceContract(factory)); + ref1.setReference(i.getReferences().get(0)); + c.getReferences().add(ref1); + ref1.getBindings().add(new TestBinding(factory)); + + ComponentReference ref2 = factory.createComponentReference(); + ref2.setName("stockQuoteService"); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + ref2.setReference(i.getReferences().get(1)); + c.getReferences().add(ref2); + ref2.getBindings().add(new TestBinding(factory)); + + ComponentService s = factory.createComponentService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + s.setService(i.getServices().get(0)); + c.getServices().add(s); + s.getBindings().add(new TestBinding(factory)); + + return c; + } + + /** + * Create a new component type + * + * @return + */ + ComponentType createComponentType() { + ComponentType ctype = factory.createComponentType(); + + Property p = factory.createProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + ctype.getProperties().add(p); + + Reference ref1 = factory.createReference(); + ref1.setName("accountDataService"); + ref1.setInterfaceContract(new TestInterfaceContract(factory)); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref1); + ref1.getBindings().add(new TestBinding(factory)); + + Reference ref2 = factory.createReference(); + ref2.setName("stockQuoteService"); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref2); + ref2.getBindings().add(new TestBinding(factory)); + + Service s = factory.createService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + ctype.getServices().add(s); + s.getBindings().add(new TestBinding(factory)); + + return ctype; + } + + /** + * Create a new constraining type + * + * @return + */ + ConstrainingType createConstrainingType() { + ConstrainingType ctype = factory.createConstrainingType(); + + AbstractProperty p = factory.createAbstractProperty(); + p.setName("currency"); + p.setValue("USD"); + p.setMustSupply(true); + p.setXSDType(new QName("", "")); + ctype.getProperties().add(p); + + AbstractReference ref1 = factory.createAbstractReference(); + ref1.setName("accountDataService"); + ref1.setInterfaceContract(new TestInterfaceContract(factory)); + ref1.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref1); + + AbstractReference ref2 = factory.createAbstractReference(); + ref2.setName("stockQuoteService"); + ref2.setInterfaceContract(new TestInterfaceContract(factory)); + ref2.setMultiplicity(Multiplicity.ONE_ONE); + ctype.getReferences().add(ref2); + + AbstractService s = factory.createAbstractService(); + s.setName("AccountService"); + s.setInterfaceContract(new TestInterfaceContract(factory)); + ctype.getServices().add(s); + + return ctype; + } + + @Test + public void testPrint1() { + Composite composite = createComposite(); + StringWriter sw = new StringWriter(); + PrintUtil p = new PrintUtil(new PrintWriter(sw), true); + p.print(composite); + // System.out.println(sw.toString()); + } + + @Test + public void testPrint2() { + Composite composite = createComposite(); + StringWriter sw = new StringWriter(); + PrintUtil p = new PrintUtil(new PrintWriter(sw), false); + p.print(composite); + // System.out.println(sw.toString()); + } +} diff --git a/branches/sca-android/tuscany-core-spi/.classpath b/branches/sca-android/tuscany-core-spi/.classpath new file mode 100644 index 0000000000..541760ca35 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/.classpath @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-core-spi/.project b/branches/sca-android/tuscany-core-spi/.project new file mode 100644 index 0000000000..9f6a857423 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/.project @@ -0,0 +1,21 @@ + + tuscany-core-spi + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-contribution + tuscany-sca-api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-core-spi/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-core-spi/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..910a03ce95 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:19:38 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-core-spi/DISCLAIMER b/branches/sca-android/tuscany-core-spi/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-core-spi/LICENSE b/branches/sca-android/tuscany-core-spi/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/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/branches/sca-android/tuscany-core-spi/NOTICE b/branches/sca-android/tuscany-core-spi/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-core-spi/pom.xml b/branches/sca-android/tuscany-core-spi/pom.xml new file mode 100644 index 0000000000..72cfbe7a7c --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/pom.xml @@ -0,0 +1,91 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-core-spi + Apache Tuscany SCA Core SPI + + + + org.apache.tuscany.sca + tuscany-extensibility + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-sca-api + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-assembly + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-definitions + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-policy + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface + 2.0-incubating-SNAPSHOT + compile + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-incubating-SNAPSHOT + + + + javax.servlet + servlet-api + 2.5 + provided + + + + org.codehaus.woodstox + wstx-asl + 3.2.1 + runtime + + + + + diff --git a/branches/sca-android/tuscany-core-spi/src/doc/Context Model.emx b/branches/sca-android/tuscany-core-spi/src/doc/Context Model.emx new file mode 100644 index 0000000000..0445ea5a6b --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/doc/Context Model.emx @@ -0,0 +1,673 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java new file mode 100644 index 0000000000..93fc219903 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.context; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.osoa.sca.ComponentContext; + +/** + * Interface implemented by the provider of the ComponentContext. + * + * @version $Rev: 557408 $ $Date: 2007-07-18 14:58:03 -0700 (Wed, 18 Jul 2007) $ + */ +public interface ComponentContextFactory { + /** + * Create an instance of ComponentContext + * + * @param component The runtime component + * @param requestContextFactory The factory to create RequestContext + * @return An instance of ComponentContext for the component + */ + ComponentContext createComponentContext(RuntimeComponent component, RequestContextFactory requestContextFactory); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.java new file mode 100644 index 0000000000..822c9ccd84 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.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.context; + +/** + * An extension point for context factories. + * + * @version $Rev: 572488 $ $Date: 2007-09-03 18:41:17 -0700 (Mon, 03 Sep 2007) $ + */ +public interface ContextFactoryExtensionPoint { + + /** + * Add a context factory extension. + * + * @param factory The factory to add + */ + void addFactory(Object factory); + + /** + * Remove a context factory extension. + * + * @param factory The factory to remove + */ + void removeFactory(Object factory); + + /** + * Get a factory implementing the given interface. + * @param factoryInterface the lookup key (factory interface) + * @return The factory + */ + T getFactory(Class factoryInterface); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.java new file mode 100644 index 0000000000..8cd0978ff0 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.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.context; + +import java.util.HashMap; + +/** + * Default implementation of a model factory extension point. + * + * @version $Rev: 557408 $ $Date: 2007-07-18 14:58:03 -0700 (Wed, 18 Jul 2007) $ + */ +public class DefaultContextFactoryExtensionPoint implements ContextFactoryExtensionPoint { + + private HashMap, Object> factories = new HashMap, Object>(); + + /** + * Add a model factory extension. + * + * @param factory The factory to add + */ + public void addFactory(Object factory) { + Class[] interfaces = factory.getClass().getInterfaces(); + for (int i = 0; i T getFactory(Class factoryInterface) { + Object factory = factories.get(factoryInterface); + return factoryInterface.cast(factory); + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java new file mode 100644 index 0000000000..fc8119578c --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.context; + +import org.apache.tuscany.sca.assembly.ComponentProperty; + +/** + * Interface implemented by the provider of the property values + */ +public interface PropertyValueFactory { + + /** + * This method will create an instance of the value for the specified Property. + * + * @param property The Property from which to retrieve the property value + * @param type The type of the property value being retrieved from the Property + * @param Type type of the property value being looked up + * + * @return the value for the Property + */ + B createPropertyValue(ComponentProperty property, Class type); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java new file mode 100644 index 0000000000..5435255708 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.context; + +import org.osoa.sca.RequestContext; + +/** + * Interface implemented by the provider of the RequestContext. + * + * @version $Rev: 557408 $ $Date: 2007-07-18 14:58:03 -0700 (Wed, 18 Jul 2007) $ + */ +public interface RequestContextFactory { + /** + * @return An instance of RequestContext for the current invocation + */ + RequestContext createRequestContext(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistry.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistry.java new file mode 100644 index 0000000000..efc2f80dc7 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/DefaultExtensionPointRegistry.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Default implementation of a registry to hold all the Tuscany core extension + * points. As the point of contact for all extension artifacts this registry + * allows loaded extensions to find all other parts of the system and register + * themselves appropriately. + * + * @version $Rev: 639350 $ $Date: 2008-03-20 09:43:46 -0700 (Thu, 20 Mar 2008) $ + */ +public class DefaultExtensionPointRegistry implements ExtensionPointRegistry { + private Map, Object> extensionPoints = new HashMap, Object>(); + + /** + * Add an extension point to the registry. This default implementation + * stores extensions against the interfaces that they implement. + * + * @param extensionPoint The instance of the extension point + */ + public void addExtensionPoint(Object extensionPoint) { + Set interfaces = getAllInterfaces(extensionPoint.getClass()); + for (Class i : interfaces) { + extensionPoints.put(i, extensionPoint); + } + } + + private Constructor getConstructor(Constructor[] constructors, Class[] paramTypes) { + for (Constructor c : constructors) { + Class types[] = c.getParameterTypes(); + if (c.getParameterTypes().length == paramTypes.length) { + boolean found = true; + for (int i = 0; i < types.length; i++) { + if (types[i] != paramTypes[i]) { + found = false; + break; + } + } + if (found) { + return c; + } + } + } + return null; + } + + /** + * Get the extension point by the interface that it implements + * + * @param extensionPointType The lookup key (extension point interface) + * @return The instance of the extension point + */ + public T getExtensionPoint(Class extensionPointType) { + Object extensionPoint = extensionPoints.get(extensionPointType); + if (extensionPoint == null) { + + // Dynamically load an extension point class declared under META-INF/services + try { + Class extensionPointClass = + ServiceDiscovery.getInstance().loadFirstServiceClass(extensionPointType); + if (extensionPointClass != null) { + // Construct the extension point + Constructor[] constructors = extensionPointClass.getConstructors(); + Constructor constructor = + getConstructor(constructors, new Class[] {ModelFactoryExtensionPoint.class}); + if (constructor != null) { + extensionPoint = constructor.newInstance(getExtensionPoint(ModelFactoryExtensionPoint.class)); + } else { + constructor = getConstructor(constructors, new Class[] {ExtensionPointRegistry.class}); + if (constructor != null) { + extensionPoint = constructor.newInstance(this); + } else { + constructor = getConstructor(constructors, new Class[] {}); + if (constructor != null) { + extensionPoint = constructor.newInstance(); + } else { + throw new IllegalArgumentException( + "No valid constructor is found for " + extensionPointClass); + } + } + } + + // Cache the loaded extension point + addExtensionPoint(extensionPoint); + } + } catch (InvocationTargetException e) { + throw new IllegalArgumentException(e); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } catch (InstantiationException e) { + throw new IllegalArgumentException(e); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + } + return extensionPointType.cast(extensionPoint); + } + + /** + * Remove an extension point based on the interface that it implements + * + * @param extensionPoint The extension point to remove + */ + public void removeExtensionPoint(Object extensionPoint) { + Set interfaces = getAllInterfaces(extensionPoint.getClass()); + for (Class i : interfaces) { + extensionPoints.remove(i); + } + } + + /** + * Returns the set of interfaces implemented by the given class and its + * ancestors or a blank set if none + */ + private static Set getAllInterfaces(Class clazz) { + Set implemented = new HashSet(); + getAllInterfaces(clazz, implemented); + return implemented; + } + + private static void getAllInterfaces(Class clazz, Set implemented) { + Class[] interfaces = clazz.getInterfaces(); + for (Class interfaze : interfaces) { +// String name = interfaze.getName(); +// if (name.startsWith("java.") || name.startsWith("javax.")) { +// continue; +// } + if (Modifier.isPublic(interfaze.getModifiers())) { + implemented.add(interfaze); + } + } + Class superClass = clazz.getSuperclass(); + // Object has no superclass so check for null + if (superClass != null && !superClass.equals(Object.class)) { + getAllInterfaces(superClass, implemented); + } + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ExtensionPointRegistry.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ExtensionPointRegistry.java new file mode 100644 index 0000000000..537c9d69d8 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ExtensionPointRegistry.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; + + +/** + * The registry for the Tuscany core extension points. As the point of contact + * for all extension artifacts this registry allows loaded extensions to find + * all other parts of the system and register themselves appropriately. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface ExtensionPointRegistry { + + /** + * Add an extension point to the registry + * @param extensionPoint The instance of the extension point + */ + void addExtensionPoint(Object extensionPoint); + + /** + * Get the extension point by the interface + * @param extensionPointType The lookup key (extension point interface) + * @return The instance of the extension point + */ + T getExtensionPoint(Class extensionPointType); + + /** + * Remove an extension point + * @param extensionPoint The extension point to remove + */ + void removeExtensionPoint(Object extensionPoint); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ModuleActivator.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ModuleActivator.java new file mode 100644 index 0000000000..1893dc57cc --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/core/ModuleActivator.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; + + +/** + * ModuleActivator represents a module that plugs into the Tuscany system. Each + * module should provide an implementation of this interface and register the + * ModuleActivator implementation class by defining a file named + * + * "META-INF/services/org.apache.tuscany.core.ModuleActivator" + * + * The content of the file is the class name of the ModuleActivator implementation. + * The implementation class must have a no-arg constructor. The same instance + * will be used to invoke all the methods during different phases of the module + * activation. Note that the start and stop methods defined by this interface + * take a reference to the Tuscany SCA runtime ExtensionPointRegistry. This + * gives the ModuleActivator the opportunity to add extension points to the + * registry as it is requested to start up and remove them when it is requested + * to shut down. + * + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface ModuleActivator { + + /** + * This method is invoked when the module is started by the Tuscany system. + * It can be used by this module to register extensions against extension + * points. + * + * @param registry The extension point registry + */ + void start(ExtensionPointRegistry registry); + + /** + * This method is invoked when the module is stopped by the Tuscany system. + * It can be used by this module to unregister extensions against the + * extension points. + * + * @param registry The extension point registry + */ + void stop(ExtensionPointRegistry registry); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/Event.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/Event.java new file mode 100644 index 0000000000..0aa922afa0 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/Event.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.event; + +/** + * The base interface for events that are propagated in the runtime + * + * @version $$Rev: 539355 $$ $$Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $$ + */ +public interface Event { + + /** + * Returns the source of the event + */ + Object getSource(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventFilter.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventFilter.java new file mode 100644 index 0000000000..00f6961235 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventFilter.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.event; + +/** + * Evaluates whether a {@link RuntimeEventListener} is applicable to a given runtime event + * + * @version $$Rev: 539355 $$ $$Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $$ + */ +public interface EventFilter { + + /** + * Performs the actual evaluation on an event + * @param event Returns true if the event matches implemented criteria + * @return Match result + */ + boolean match(Event event); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventPublisher.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventPublisher.java new file mode 100644 index 0000000000..4a204efdd1 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/EventPublisher.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.event; + +/** + * Publishes events in the runtime by accepting {@link Event} objects and + * forwarding them to all registered {@link RuntimeEventListener} objects. + * + * @version $$Rev: 639280 $$ $$Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $$ + */ +public interface EventPublisher { + + /** + * Publish an event to all registered listeners + * @param object The event to publish + */ + void publish(Event object); + + /** + * Registers a listener to receive notifications for the context + * @param listener The listener to add + */ + void addListener(RuntimeEventListener listener); + + /** + * Registers a listener to receive notifications for the context + * @param filter The filter that will be applied before the lister is called + * @param listener The lister to add + */ + void addListener(EventFilter filter, RuntimeEventListener listener); + + + /** + * Removes a previously registered listener + * @param listener The listener to remove + */ + void removeListener(RuntimeEventListener listener); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/RuntimeEventListener.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/RuntimeEventListener.java new file mode 100644 index 0000000000..e540ef683e --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/RuntimeEventListener.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.event; + +import java.util.EventListener; + +/** + * Listeners observe events fired in the SCA runtime. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface RuntimeEventListener extends EventListener { + + /** + * Accepts and event and acts on it + * @param event The event to act on + */ + void onEvent(Event event); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/TrueFilter.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/TrueFilter.java new file mode 100644 index 0000000000..177dcfbb77 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/event/TrueFilter.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.event; + +/** + * An event filter that always returns a true condition + * + * @version $$Rev: 539355 $$ $$Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $$ + */ +public class TrueFilter implements EventFilter { + + /** + * Performs the actual evaluation on an event. Always returns true + * in this case + * @param event The incoming event which is ignored + * @return true + */ + public boolean match(Event event) { + return true; + } +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.java new file mode 100644 index 0000000000..dec01a119b --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.invocation; + +/** + * An invoker or interceptor can optionally implement this interface to indicate if they can + * enforce the pass-by-value semantics for an operation on remotable interfaces. + * + * @version $Rev: 634778 $ $Date: 2008-03-07 10:58:16 -0800 (Fri, 07 Mar 2008) $ + */ +public interface DataExchangeSemantics { + /** + * Indicate if the data can be passed in by reference as they won't be mutated. + * @return true if pass-by-reference is allowed + */ + boolean allowsPassByReference(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.java new file mode 100644 index 0000000000..a5d6daab23 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.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.invocation; + +/** + * Synchronous mediation associated with a client- or target- side wire. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface Interceptor extends Invoker { + + /** + * Sets the next invoker + * @param next The next invoker + */ + void setNext(Invoker next); + + /** + * Returns the next invoker or null + * @return The next Invoker + */ + Invoker getNext(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java new file mode 100644 index 0000000000..37d15a8704 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.invocation; + +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * A wire consists of 1..n invocation chains associated with the operations of its source service contract. + *

+ * Invocation chains may contain Interceptors that process invocations. + *

+ * A Message is used to pass data associated with an invocation through the chain. + * + * @version $Rev: 632064 $ $Date: 2008-02-28 09:18:51 -0800 (Thu, 28 Feb 2008) $ + */ +public interface InvocationChain { + /** + * Returns the target operation for this invocation chain. + * + * @return The target operation for this invocation chain + */ + Operation getTargetOperation(); + + /** + * Updates the target operation for this invocation chain. + * + * @param operation The new target operation for this invocation chain + */ + void setTargetOperation(Operation operation); + + /** + * Returns the source operation for this invocation chain. + * + * @return The source operation for this invocation chain + */ + Operation getSourceOperation(); + + /** + * Adds an interceptor to the chain. For reference side, it will be added to + * Phase.REFERENCE. For service side, it will be added to Phase.SERVICE + * + * @param interceptor The interceptor to add + */ + void addInterceptor(Interceptor interceptor); + + /** + * Adds an invoker to the chain + * + * @param invoker The invoker to add + */ + void addInvoker(Invoker invoker); + + /** + * Returns the first invoker in the chain. + * + * @return The first invoker in the chain + */ + Invoker getHeadInvoker(); + + /** + * @deprecated This method is not used + * Returns the last invoker in the chain. + * + * @return The last invoker in the chain + */ + @Deprecated + Invoker getTailInvoker(); + + /** + * @deprecated Please use void addInterceptor(String phase, Interceptor interceptor); + * Adds an interceptor at the given position in the interceptor stack + * + * @param index The position in the interceptor stack to add the interceptor + * @param interceptor The interceptor to add + */ + @Deprecated + void addInterceptor(int index, Interceptor interceptor); + + /** + * Add an interceptor to the given phase + * @param phase + * @param interceptor + */ + void addInterceptor(String phase, Interceptor interceptor); + + /** + * Indicate if the data can be passed in by reference as they won't be mutated. + * @return true if pass-by-reference is allowed + */ + boolean allowsPassByReference(); + /** + * Force the invocation to allow pass-by-reference + * @param allowsPBR + */ + void setAllowsPassByReference(boolean allowsPBR); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.java new file mode 100644 index 0000000000..95efa3d259 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.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.invocation; + +/** + * Synchronous mediation associated with a client- or target- side wire. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface Invoker { + + /** + * Process a synchronous wire + * + * @param msg The request Message for the wire + * @return The response Message from the wire + */ + Message invoke(Message msg); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.java new file mode 100644 index 0000000000..b28f6ad483 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.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.invocation; + +import java.util.Map; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.runtime.EndpointReference; + +/** + * Represents a request, response, or exception flowing through a wire + * + * @version $Rev $Date + */ +public interface Message { + String QOS_CTX_SECURITY_PRINCIPAL = "PRINCIPAL"; + + /** + * Returns the body of the message, which will be the payload or parameters associated with the wire + * @return The body of the message + */ + T getBody(); + + /** + * Sets the body of the message. + * @param body The body of the message + */ + void setBody(T body); + + /** + * Get the end point reference of the source reference + * @return The end point reference of the reference originating the message + */ + EndpointReference getFrom(); + + /** + * Set the end point reference of the reference originating the message + * @param from The end point reference of the reference originating the message + */ + void setFrom(EndpointReference from); + + /** + * Get the end point reference of target service + * @return The end point reference of the service that the message targets + */ + EndpointReference getTo(); + + /** + * Set the end point reference of target service + * @param to The end point reference of the service that the message targets + */ + void setTo(EndpointReference to); + + /** + * Returns the id of the message + * @return The message Id + */ + Object getMessageID(); + + /** + * Sets the id of the message + * @param messageId The message ID + */ + void setMessageID(Object messageId); + + /** + * Determines if the message represents a fault/exception + * + * @return true If the message body is a fault object, false if the body is a normal payload + */ + boolean isFault(); + + /** + * Set the message body with a fault object. After this method is called, isFault() returns true. + * + * @param fault The fault object represents an exception + */ + void setFaultBody(T fault); + + /** + * Returns the operation that created the message. + * + * @return The operation that created the message + */ + Operation getOperation(); + + /** + * Sets the operation that created the message. + * + * @param op The operation that created the message + */ + void setOperation(Operation op); + + /** + * Returns a map of objects that represents the QoS context that wraps this message such as + * invoking authenticated principal and so on. + * + * @return + */ + Map getQoSContext(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.java new file mode 100644 index 0000000000..9a452b5d54 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.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.invocation; + + +/** + * A factory for messages + * + * @version $Rev $Date + */ +public interface MessageFactory { + + /** + * Creates a new message. + * + * @return The new message + */ + Message createMessage(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java new file mode 100644 index 0000000000..82b994577f --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.invocation; + +/** + * Tuscany built-in phases for the invocation chain + * + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface Phase { + // The first phase for outgoing invocations via a reference + String REFERENCE = "component.reference"; + + // data transformation and validation + String REFERENCE_INTERFACE = "reference.interface"; + + // reference policy handling + String REFERENCE_POLICY = "reference.policy"; + + // reference binding invoker + String REFERENCE_BINDING = "reference.binding"; + + // The first phase for incoming invocations via a service + String SERVICE_BINDING = "service.binding"; + + // service policy handling + String SERVICE_POLICY = "service.policy"; + + // data validation and transformation + String SERVICE_INTERFACE = "service.interface"; + + // TODO: not sure if we need to have this face + String SERVICE = "component.service"; + + // implementation policy handling + String IMPLEMENTATION_POLICY = "implementation.policy"; + + // implementation invoker + String IMPLEMENTATION = "component.implementation"; + + // String getName(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java new file mode 100644 index 0000000000..49bceac82b --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.management; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Interface for the management service abstraction. The implementation + * could be based on a variety of technologies including JMX, WSDM, + * SNMP etc. + * + * @version $Revision: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface ManagementService { + + /** + * Registers a component for management. + * + * @param name Name of the component. + * @param component Component to be registered. + */ + void registerComponent(String name, RuntimeComponent component); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.java new file mode 100644 index 0000000000..900450f206 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.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.provider; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * A factory for creating the runtime artifacts that represent bindings. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface BindingProviderFactory extends ProviderFactory { + + /** + * Creates a new reference binding provider for the given component and + * reference. + * + * @param component The runtime component + * @param reference The reference on the runtime component + * @param binding The binding assembly model object + * @return The binding provider + */ + ReferenceBindingProvider createReferenceBindingProvider(RuntimeComponent component, + RuntimeComponentReference reference, + M binding); + + /** + * Creates a new service binding provider for the given component and + * service. + * + * @param component The runtime component + * @param service The service on the runtime component + * @param binding The binding assembly model object + * @return The binding provider + */ + ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, + M binding); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java new file mode 100644 index 0000000000..371f9c9af2 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java @@ -0,0 +1,370 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.provider; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Default implementation of a provider factory extension point. + * + * @version $Rev: 634558 $ $Date: 2008-03-06 22:35:52 -0800 (Thu, 06 Mar 2008) $ + */ +public class DefaultProviderFactoryExtensionPoint implements ProviderFactoryExtensionPoint { + + private ExtensionPointRegistry registry; + private final Map, ProviderFactory> providerFactories = new HashMap, ProviderFactory>(); + private final List policyProviderFactories = new ArrayList(); + private boolean loaded; + + /** + * The default constructor. Does nothing. + * + */ + public DefaultProviderFactoryExtensionPoint(ExtensionPointRegistry registry) { + this.registry = registry; + } + + /** + * Add a provider factory. + * + * @param providerFactory The provider factory + */ + public void addProviderFactory(ProviderFactory providerFactory) { + if(providerFactory instanceof PolicyProviderFactory) { + policyProviderFactories.add((PolicyProviderFactory)providerFactory); + } + providerFactories.put(providerFactory.getModelType(), providerFactory); + } + + /** + * Remove a provider factory. + * + * @param providerFactory The provider factory + */ + public void removeProviderFactory(ProviderFactory providerFactory) { + if(providerFactory instanceof PolicyProviderFactory) { + policyProviderFactories.remove((PolicyProviderFactory)providerFactory); + } + providerFactories.remove(providerFactory.getModelType()); + } + + /** + * Returns the provider factory associated with the given model type. + * @param modelType A model type + * @return The provider factory associated with the given model type + */ + public ProviderFactory getProviderFactory(Class modelType) { + loadProviderFactories(); + + Class[] classes = modelType.getInterfaces(); + for (Class c : classes) { + ProviderFactory factory = providerFactories.get(c); + if (factory != null) { + return factory; + } + } + return providerFactories.get(modelType); + } + + public List getPolicyProviderFactories() { + loadProviderFactories(); + return policyProviderFactories; + } + + /** + * Load provider factories declared under META-INF/services. + * @param registry + */ + private void loadProviderFactories() { + if (loaded) + return; + + loadProviderFactories(BindingProviderFactory.class); + loadProviderFactories(ImplementationProviderFactory.class); + loadProviderFactories(PolicyProviderFactory.class); + + loaded = true; + } + + /** + * Load provider factories declared under META-INF/services. + * @param registry + * @param factoryClass + * @return + */ + private List loadProviderFactories(Class factoryClass) { + + // Get the provider factory service declarations + Set factoryDeclarations; + ServiceDiscovery serviceDiscovery = ServiceDiscovery.getInstance(); + try { + factoryDeclarations = serviceDiscovery.getServiceDeclarations(factoryClass); + } catch (Exception e) { + throw new IllegalStateException(e); + } + // Get the target extension point + + ProviderFactoryExtensionPoint factoryExtensionPoint = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + if (factoryExtensionPoint == null) { + factoryExtensionPoint = new DefaultProviderFactoryExtensionPoint(registry); + registry.addExtensionPoint(factoryExtensionPoint); + + } + + List factories = new ArrayList(); + + for (ServiceDeclaration factoryDeclaration : factoryDeclarations) { + Map attributes = factoryDeclaration.getAttributes(); + + // Load an implementation provider factory + if (factoryClass == ImplementationProviderFactory.class) { + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + ImplementationProviderFactory factory = + new LazyImplementationProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + + } else if (factoryClass == BindingProviderFactory.class) { + + // Load a binding provider factory + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + BindingProviderFactory factory = + new LazyBindingProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + } else if (factoryClass == PolicyProviderFactory.class) { + // Load a policy provider factory + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + PolicyProviderFactory factory = + new LazyPolicyProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + + } + } + return factories; + } + + /** + * A wrapper around an implementation provider factory allowing lazy + * loading and initialization of implementation providers. + */ + private static class LazyBindingProviderFactory implements BindingProviderFactory { + + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration factoryDeclaration; + private BindingProviderFactory factory; + private Class modelType; + + private LazyBindingProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration factoryDeclaration) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.factoryDeclaration = factoryDeclaration; + } + + @SuppressWarnings("unchecked") + private BindingProviderFactory getFactory() { + if (factory == null) { + try { + Class factoryClass = + (Class)factoryDeclaration.loadClass(); + Constructor constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + @SuppressWarnings("unchecked") + public ReferenceBindingProvider createReferenceBindingProvider(RuntimeComponent component, + RuntimeComponentReference reference, + Binding binding) { + return getFactory().createReferenceBindingProvider(component, reference, binding); + } + + @SuppressWarnings("unchecked") + public ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component, + RuntimeComponentService service, + Binding binding) { + return getFactory().createServiceBindingProvider(component, service, binding); + } + + public Class getModelType() { + if (modelType == null) { + try { + modelType = factoryDeclaration.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + } + + /** + * A wrapper around an implementation provider factory allowing lazy + * loading and initialization of implementation providers. + */ + private class LazyImplementationProviderFactory implements ImplementationProviderFactory { + + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration providerClass; + private ImplementationProviderFactory factory; + private Class modelType; + + private LazyImplementationProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration providerClass) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.providerClass = providerClass; + } + + @SuppressWarnings("unchecked") + private ImplementationProviderFactory getFactory() { + if (factory == null) { + try { + Class factoryClass = + (Class)providerClass.loadClass(); + Constructor constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + @SuppressWarnings("unchecked") + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + Implementation Implementation) { + return getFactory().createImplementationProvider(component, Implementation); + } + + public Class getModelType() { + if (modelType == null) { + try { + + modelType = providerClass.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + } + + /** + * A wrapper around an policy provider factory allowing lazy + * loading and initialization of policy providers. + */ + private class LazyPolicyProviderFactory implements PolicyProviderFactory { + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration providerClass; + private PolicyProviderFactory factory; + private Class modelType; + + private LazyPolicyProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration providerClass) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.providerClass = providerClass; + } + + @SuppressWarnings("unchecked") + private PolicyProviderFactory getFactory() { + if (factory == null) { + try { + Class factoryClass = (Class)providerClass.loadClass(); + Constructor constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + public PolicyProvider createImplementationPolicyProvider(RuntimeComponent component, + Implementation implementation) { + return getFactory().createImplementationPolicyProvider(component, implementation); + } + + public PolicyProvider createReferencePolicyProvider(RuntimeComponent component, + RuntimeComponentReference reference, + Binding binding) { + return getFactory().createReferencePolicyProvider(component, reference, binding); + } + + public PolicyProvider createServicePolicyProvider(RuntimeComponent component, + RuntimeComponentService service, + Binding binding) { + return getFactory().createServicePolicyProvider(component, service, binding); + } + + public Class getModelType() { + if (modelType == null) { + try { + modelType = providerClass.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultSCADefinitionsProviderExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultSCADefinitionsProviderExtensionPoint.java new file mode 100644 index 0000000000..4cca3b1e32 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultSCADefinitionsProviderExtensionPoint.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Concrete Implementation for the SCADefinitionsProviderExtensionPoint + */ +public class DefaultSCADefinitionsProviderExtensionPoint implements + SCADefinitionsProviderExtensionPoint { + + private ExtensionPointRegistry extensionPointRegistry = null; + + private List scaDefnsProviders = new ArrayList(); + + public DefaultSCADefinitionsProviderExtensionPoint(ExtensionPointRegistry extnPtReg) { + this.extensionPointRegistry = extnPtReg; + } + + public void addSCADefinitionsProvider(SCADefinitionsProvider provider) { + scaDefnsProviders.add(provider); + } + + public void removeSCADefinitionsProvider(SCADefinitionsProvider provider) { + scaDefnsProviders.remove(provider); + } + + public List getSCADefinitionsProviders() { + if (scaDefnsProviders.isEmpty()) { + loadProviders(); + } + return scaDefnsProviders; + } + + private void loadProviders() { + // Get the provider service declarations + Set defnProviderDecls; + SCADefinitionsProvider aProvider = null; + Class providerClass = null; + Constructor constructor = null; + + try { + defnProviderDecls = + ServiceDiscovery.getInstance().getServiceDeclarations(SCADefinitionsProvider.class); + + for (ServiceDeclaration aDefnProviderDecl : defnProviderDecls) { + providerClass = aDefnProviderDecl.loadClass(); + + try { + constructor = providerClass.getConstructor(); + aProvider = (SCADefinitionsProvider)constructor.newInstance(); + } catch (NoSuchMethodException e1) { + constructor = providerClass.getConstructor(ExtensionPointRegistry.class); + aProvider = (SCADefinitionsProvider)constructor.newInstance(extensionPointRegistry); + } + + scaDefnsProviders.add(aProvider); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + } +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.java new file mode 100644 index 0000000000..a9f86c45ca --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.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.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * A component implementation can implement this interface in order to tie + * into the Tuscany runtime + * + * @version $Rev: 576260 $ $Date: 2007-09-16 22:17:22 -0700 (Sun, 16 Sep 2007) $ + */ +public interface ImplementationProvider { + + /** + * This method will be invoked when the component implementation + * is activated. + */ + void start(); + + /** + * This method will be invoked when the component implementation + * is deactivated. + */ + void stop(); + + /** + * Create an invoker for the component implementation in the invocation + * chain. The invoker will be responsible for calling the implementation + * logic for the given component. + * + * @param service The component service + * @param operation The operation that the interceptor will handle + * @return An invoker that handles the invocation logic, null should be + * returned if no invoker is required + */ + Invoker createInvoker(RuntimeComponentService service, Operation operation); + + /** + * For bindings that invoke one-way callback operations asynchronously, + * there is no need to perform a thread switch before calling the invoker. + * This method indicates whether the binding has this capability. + * + * @return true if the callback invoker is able to invoke one-way operations + * asynchronously, false if all invocations are synchronous + */ + boolean supportsOneWayInvocation(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java new file mode 100644 index 0000000000..084056278c --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * An interface for factories that create implementation providers. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface ImplementationProviderFactory extends ProviderFactory { + + /** + * Creates a new implementation provider for the given + * component. + * + * @param component The runtime component + * @param Implementation The implementation type + * @return The implementation provider + */ + ImplementationProvider createImplementationProvider(RuntimeComponent component, M Implementation); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java new file mode 100644 index 0000000000..7e798549b3 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import java.util.List; + +import javax.xml.namespace.QName; + +/** + * This interface can be optionally implemented by the Binding or Implementation providers to + * indicate if they implement the policies in the binding/implementation provider. + * + * @version $Rev: 634558 $ $Date: 2008-03-06 22:35:52 -0800 (Thu, 06 Mar 2008) $ + */ +public interface PolicyImplementor { + /** + * Get a list of policy names that are implemented by this policy implementor + * @return A list of policy names + */ + List getImplementedPolicies(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java new file mode 100644 index 0000000000..b7306e48dd --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; + +/** + * @version $Rev: 634558 $ $Date: 2008-03-06 22:35:52 -0800 (Thu, 06 Mar 2008) $ + */ +public interface PolicyProvider { + /** + * Create an interceptor for a given operation + * @param operation + * @return An interceptor that realize the policySet + */ + Interceptor createInterceptor(Operation operation); + + /** + * Get the phase that the interceptor should be added + * @return The phase that this interceptor belongs to + */ + String getPhase(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.java new file mode 100644 index 0000000000..d7e4fee1d9 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.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.provider; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.policy.Policy; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * @version $Rev: 634558 $ $Date: 2008-03-06 22:35:52 -0800 (Thu, 06 Mar 2008) $ + */ +public interface PolicyProviderFactory extends ProviderFactory { + /** + * Create policy provider for a given reference binding + * @param component + * @param reference + * @param binding + * @return + */ + PolicyProvider createReferencePolicyProvider(RuntimeComponent component, + RuntimeComponentReference reference, + Binding binding); + + /** + * Create policy provider for a given service binding + * @param component + * @param service + * @param binding + * @return + */ + PolicyProvider createServicePolicyProvider(RuntimeComponent component, + RuntimeComponentService service, + Binding binding); + + /** + * Create policy provider for a given component implementation + * @param component + * @param implementation + * @return + */ + PolicyProvider createImplementationPolicyProvider(RuntimeComponent component, Implementation implementation); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.java new file mode 100644 index 0000000000..e0c03b3db1 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.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.provider; + +/** + * A factory for runtime providers. + * + * @version $Rev: 537206 $ $Date: 2007-05-11 08:14:19 -0700 (Fri, 11 May 2007) $ + */ +public interface ProviderFactory { + + /** + * The model type that this factory creates providers for. + * + * @return the model type + */ + Class getModelType(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.java new file mode 100644 index 0000000000..63c8cc162b --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.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.provider; + +import java.util.List; + + +/** + * An extension point for provider factories. Holds all of the provider + * factories from loaded extension points. Allows a provider factory + * to be located based on a given model type. Hence the runtime can + * generate runtime artifacts from the in memory assembly model. + * + * @version $Rev: 634558 $ $Date: 2008-03-06 22:35:52 -0800 (Thu, 06 Mar 2008) $ + */ +public interface ProviderFactoryExtensionPoint { + + + /** + * Add a provider factory. + * + * @param providerFactory The provider factory + */ + void addProviderFactory(ProviderFactory providerFactory); + + /** + * Remove a provider factory. + * + * @param providerFactory The provider factory + */ + void removeProviderFactory(ProviderFactory providerFactory); + + /** + * Returns the provider factory associated with the given model type. + * @param modelType A model type + * @return The provider factory associated with the given model type + */ + ProviderFactory getProviderFactory(Class modelType); + + /** + * Get a list of registered PolicyProviderFactory + * @return a list of registered PolicyProviderFactory + */ + List getPolicyProviderFactories(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.java new file mode 100644 index 0000000000..d0a1b53563 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.provider; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; + +/** + * A reference binding implementation can options implement this + * interface to tie into the Tuscany SCA runtime + * + * @version $Rev: 576260 $ $Date: 2007-09-16 22:17:22 -0700 (Sun, 16 Sep 2007) $ + */ +public interface ReferenceBindingProvider { + + /** + * This method will be invoked when the component reference binding is + * activated. + */ + void start(); + + /** + * This method will be invoked when the component reference binding is + * deactivated. + */ + void stop(); + + /** + * Create an invoker for the reference binding in the invocation chain. The + * invoker is responsible for making the outbound invocation over the + * binding protocol. + * + * @param operation The operation that the interceptor will handle + * @return An invoker that handles the invocation logic, null should be + * returned if no invoker is required + */ + Invoker createInvoker(Operation operation); + + /** + * Get the effective interface contract imposed by the binding. For example, + * it will be interface contract introspected from the WSDL portType used by + * the endpoint for a WebService binding. + * + * @return The effective interface contract, if null is returned, the + * interface contract for the component reference will be used + */ + InterfaceContract getBindingInterfaceContract(); + + /** + * For bindings that invoke one-way operations asynchronously, there is no + * need to perform a thread switch before calling the invoker. This method + * indicates whether the binding has this capability. + * + * @return true if the binding invoker is able to invoke one-way operations + * asynchronously, false if all invocations are synchronous + */ + boolean supportsOneWayInvocation(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProvider.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProvider.java new file mode 100644 index 0000000000..b85d19ba9a --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProvider.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import org.apache.tuscany.sca.definitions.SCADefinitions; + +/** + * Models a provider of SCA Definitions. Typically SCA Definitions providers + * may either load a definitions.xml file or create the SCA Definitions model + * programmatically. + */ +public interface SCADefinitionsProvider { + SCADefinitions getSCADefinition() throws SCADefinitionsProviderException ; +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderException.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderException.java new file mode 100644 index 0000000000..9be99c389c --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderException.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +/** + * @version $Rev: 643489 $ $Date: 2008-04-01 10:06:42 -0800 (Tue, 01 Apr 2008) $ + */ +public class SCADefinitionsProviderException extends Exception { + + public SCADefinitionsProviderException(Throwable e) { + super(e); + } +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderExtensionPoint.java new file mode 100644 index 0000000000..4d91480295 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/SCADefinitionsProviderExtensionPoint.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import java.util.List; + +/** + * An extension point for SCA Definitions Providers. SCA Definition providers, load SCA Definitions + * items that are being specifically contributed by the module that hosts the provider in question. + */ +public interface SCADefinitionsProviderExtensionPoint { + + void addSCADefinitionsProvider(SCADefinitionsProvider provider); + void removeSCADefinitionsProvider(SCADefinitionsProvider provider); + List getSCADefinitionsProviders(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.java new file mode 100644 index 0000000000..db08098ae8 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.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.provider; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * A service binding can optionally implement this interface to tie + * into the Tuscany SCA runtime + * + * @version $Rev: 576260 $ $Date: 2007-09-16 22:17:22 -0700 (Sun, 16 Sep 2007) $ + */ +public interface ServiceBindingProvider { + /** + * This method will be invoked when the component service binding is + * activated. + */ + void start(); + + /** + * This method will be invoked when the component service binding is + * deactivated. + */ + void stop(); + + /** + * Get the effective interface contract imposed by the binding. For example, + * it will be interface contract introspected from the WSDL portType used by + * the endpoint for a WebService binding. + * + * @return The effective interface contract, if null is returned, the + * interface contract for the component service will be used + */ + InterfaceContract getBindingInterfaceContract(); + + /** + * For bindings that invoke one-way callback operations asynchronously, + * there is no need to perform a thread switch before calling the invoker. + * This method indicates whether the binding has this capability. + * + * @return true if the callback invoker is able to invoke one-way operations + * asynchronously, false if all invocations are synchronous + */ + boolean supportsOneWayInvocation(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.java new file mode 100644 index 0000000000..fb58c72262 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.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.runtime; + +import java.util.ArrayList; +import java.util.List; + + +/** + * The default implementation of a WireProcessorExtensionPoint + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public class DefaultWireProcessorExtensionPoint implements RuntimeWireProcessorExtensionPoint { + + /** + * The list of WireProcessors available to the runtime + */ + private final List processors = new ArrayList(); + + /** + * Registers a wire-processor in the runtime + * + * @param processor The processor to register + */ + public void addWireProcessor(RuntimeWireProcessor processor) { + processors.add(processor); + } + + /** + * De-registers a wire-processor in the runtime + * + * @param processor The processor to de-register + */ + public void removeWireProcessor(RuntimeWireProcessor processor) { + processors.remove(processor); + } + + /** + * Returns a list of registered wire-processors. + * + * @return The list of wire processors + */ + public List getWireProcessors() { + return processors; + } +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReference.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReference.java new file mode 100644 index 0000000000..0e7a1ce103 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReference.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.runtime; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * The endpoint reference for a component service or reference + * + * @version $Rev: 576055 $ $Date: 2007-09-16 00:11:45 -0700 (Sun, 16 Sep 2007) $ + */ +public interface EndpointReference extends Cloneable { + /** + * Get the component for the endpoint + * @return The component, null of the EPR is for a non-SCA service + */ + RuntimeComponent getComponent(); + + /** + * Get the component service or reference for the endpoint + * @return The component service or reference, null if the EPR is for a non-SCA service + */ + Contract getContract(); + + /** + * Get the binding for the endpoint + * @return The binding + */ + Binding getBinding(); + + /** + * Get the interface contract for the endpoint + * @return The interface contract + */ + InterfaceContract getInterfaceContract(); + + /** + * Update the interface contract for the endpoint + * @param interfaceContract The updated interface contract + */ + void setInterfaceContract(InterfaceContract interfaceContract); + + /** + * Get the URI for this endpoint + * @return The URI of the endpoint + */ + String getURI(); + + /** + * Set the URI for this endpoint + * @param uri The new URI of the endpoint + */ + void setURI(String uri); + + /** + * Get the callback endpoint for this endpoint + * @return The callback endpoint for this endpoint + */ + EndpointReference getCallbackEndpoint(); + + /** + * Set the callback endpoint for this endpoint + * @param callbackEndpoint The new callback endpoint for this endpoint + */ + void setCallbackEndpoint(EndpointReference callbackEndpoint); + + Object clone() throws CloneNotSupportedException; + + void setReferenceParameters(ReferenceParameters parameters); + ReferenceParameters getReferenceParameters(); + + void mergeEndpoint(EndpointReference epr); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java new file mode 100644 index 0000000000..b4ec354988 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.runtime; + +/** + * Parameters for the EndPointReference + * + * @version $Rev: 574648 $ $Date: 2007-09-11 10:45:36 -0700 (Tue, 11 Sep 2007) $ + */ +public interface ReferenceParameters extends Cloneable { + /** + * Get the callback ID + * @return the callbackID + */ + Object getCallbackID(); + + /** + * Set the callback ID + * @param callbackID the callbackID to set + */ + void setCallbackID(Object callbackID); + + /** + * Get the conversation ID + * @return the conversationID + */ + Object getConversationID(); + + /** + * Set the conversation ID + * @param conversationID the conversationID to set + */ + void setConversationID(Object conversationID); + + /** + * Get the ID for the non-ServiceReference callback object + * @return + */ + Object getCallbackObjectID(); + + /** + * Set the ID for the non-ServiceReference callback object + * @param callbackObjectID + */ + void setCallbackObjectID(Object callbackObjectID); + + EndpointReference getCallbackReference(); + + void setCallbackReference(EndpointReference callback); + + Object clone() throws CloneNotSupportedException; +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java new file mode 100644 index 0000000000..f640d9a227 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.runtime; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; + +/** + * The runtime component interface. Provides the bridge between the + * assembly model representation of a component and its runtime + * realization. + * + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface RuntimeComponent extends Component { + /** + * Set the implementation-specific configuration for this component + * @param implementationProvider The object that manages the component implementation + */ + void setImplementationProvider(ImplementationProvider implementationProvider); + + /** + * Get the implementation-specific configuration for this component + * @return The implementation provider for this component + */ + ImplementationProvider getImplementationProvider(); + + /** + * Get the associated component context + * @return + */ + RuntimeComponentContext getComponentContext(); + + /** + * Set the associated component context + * @param context + */ + void setComponentContext(RuntimeComponentContext context); + + /** + * Tests if the RuntimeComponent is started + * @return true if the RuntimeComponent is started otherwise false + */ + boolean isStarted(); + + /** + * Sets the RuntimeComponent started state + * @param the state to set + */ + void setStarted(boolean started); + + /** + * Add a policy provider to the component + * @param policyProvider + */ + void addPolicyProvider(PolicyProvider policyProvider); + + /** + * Get a list of policy providers configured for this component + * @return + */ + List getPolicyProviders(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java new file mode 100644 index 0000000000..f10c6c6e5d --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.runtime; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.ServiceReference; + +/** + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface RuntimeComponentContext extends ComponentContext { + /** + * Activate the reference (creating runtime wires) + * @param reference + */ + void start(RuntimeComponentReference reference); + + /** + * Deserialize the component reference + * @param reader + * @return A component that contains the reference + * @throws IOException + */ + RuntimeComponent read(Reader reader) throws IOException; + + /** + * Serialize the component reference + * @param reference + * @param writer + * @throws IOException + */ + void write(RuntimeComponentReference reference, Writer writer) throws IOException; + + /** + * Get the CallableReference for a given component reference + * @param + * @param businessInterface The business interface + * @param reference The reference to be wired + * @param binding The binding to be used, if it's null, either binding.sca or the 1st binding + * will be selected + * @return A service reference representing the wire + */ + ServiceReference getServiceReference(Class businessInterface, + RuntimeComponentReference reference, + Binding binding); + + /** + * Bind the reference to a target component/componentService + * @param + * @param businessInterface The business interface + * @param reference The reference to be wired + * @param component The target component + * @param service The target component service + * @return A service reference representing the wire + */ + ServiceReference getServiceReference(Class businessInterface, + RuntimeComponentReference reference, + RuntimeComponent component, + RuntimeComponentService service); + + /** + * Create a CallableReference for the given component service + * @param + * @param businessInterface + * @param component + * @param service + * @return + */ + CallableReference getCallableReference(Class businessInterface, + RuntimeComponent component, + RuntimeComponentService service); + + /** + * @param + * @param businessInterface + * @param service + * @return + */ + ServiceReference createSelfReference(Class businessInterface, ComponentService service); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java new file mode 100644 index 0000000000..f30c92452b --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.runtime; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; + +/** + * The runtime component reference. Provides the bridge between the + * assembly model representation of a component reference and its runtime + * realization + * + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface RuntimeComponentReference extends ComponentReference { + + /** + * Get a list of runtime wires to the reference + * + * @return The list of wires + */ + List getRuntimeWires(); + + /** + * Get the runtime wire for the given binding + * @param binding The assembly model binding + * @return The runtime wire + */ + RuntimeWire getRuntimeWire(Binding binding); + + /** + * Returns the reference binding provider associated with this + * component reference and the given binding. + * + * @param binding The assembly model binding + * @return The runtime reference binding provider + */ + ReferenceBindingProvider getBindingProvider(Binding binding); + + /** + * Sets the reference binding provider associated with this + * component reference and the given binding. + * + * @param binding The assembly model binding + * @param bindingProvider The runtime reference binding provider + */ + void setBindingProvider(Binding binding, ReferenceBindingProvider bindingProvider); + + /** + * Add a policy provider for the given binding to the reference + * @param binding The assembly model binding + * @param policyProvider The policy handler + */ + void addPolicyProvider(Binding binding, PolicyProvider policyProvider); + + /** + * Get a list of policy providers for the given binding + * @param binding The assembly model binding + * @return A list of policy providers for the given binding + */ + List getPolicyProviders(Binding binding); + + /** + * Get the invoker for the given binding and operation + * @param binding The assembly model binding + * @param operation The assembly model operation + * @return The runtime Invoker + */ + Invoker getInvoker(Binding binding, Operation operation); + + /** + * Set the owning component + * @param component + */ + void setComponent(RuntimeComponent component); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java new file mode 100644 index 0000000000..002bc90010 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.runtime; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentService; +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; + +/** + * The runtime component service. Provides the bridge between the + * assembly model representation of a component service and its runtime + * realization + * + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface RuntimeComponentService extends ComponentService { + + /** + * Get a list of runtime wires to the service + * + * @return The list of wires + */ + List getRuntimeWires(); + /** + * Get the runtime wire for the given binding + * @param binding The assembly model binding + * @return The runtime wire + */ + RuntimeWire getRuntimeWire(Binding binding); + + /** + * Get the callback wires associated with this service + * + * @return The list of runtime callback wires + */ + List getCallbackWires(); + + /** + * Returns the service binding provider associated with this + * component service and the given binding. + * + * @param binding The assembly model binding + * @return The runtime service binding provider + */ + ServiceBindingProvider getBindingProvider(Binding binding); + + /** + * Returns the service binding provider associated with this + * component service and the given binding. + * + * @param binding + * @param interfaceContract + * @return + */ + RuntimeWire getRuntimeWire(Binding binding, InterfaceContract interfaceContract); + + /** + * Sets the service binding provider associated with this + * component service and the given binding. + * + * @param binding The assembly model binding + * @param bindingProvider The runtime service binding provider + */ + void setBindingProvider(Binding binding, ServiceBindingProvider bindingProvider); + + /** + * Get the invoker for the given binding and operation + * @param binding The assembly model binding + * @param operation The assembly model operation + * @return The runtime invoker + */ + Invoker getInvoker(Binding binding, Operation operation); + + /** + * Get the invoker for the given binding and operation + * @param binding The assembly model binding + * @param interfaceContract the client interface contract + * @param operation The assembly model operation + * @return The runtime invoker + */ + Invoker getInvoker(Binding binding, InterfaceContract interfaceContract, Operation operation); + + /** + * Get the invocation chain for the given binding and operation + * @param binding The assembly model binding + * @param operation The assembly model operation + * @return The runtime invocation chain + */ + InvocationChain getInvocationChain(Binding binding, Operation operation); + + /** + * Get the invocation chain for the given binding and operation + * @param binding The assembly model binding + * @param operation The assembly model operation + * @param interfaceContract the client interface contract + * @return The runtime invocation chain + */ + InvocationChain getInvocationChain(Binding binding, InterfaceContract interfaceContract, Operation operation); + + /** + * Add a policy provider for the given binding to the service + * @param binding The assembly model binding + * @param policyProvider The policy handler + */ + void addPolicyProvider(Binding binding, PolicyProvider policyProvider); + + /** + * Get a list of policy providers for the given binding + * @param binding The assembly model binding + * @return A list of policy providers for the given binding + */ + List getPolicyProviders(Binding binding); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWire.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWire.java new file mode 100644 index 0000000000..104a490fa4 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWire.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.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Message; + +/** + * The runtime wire interface that connects a component reference to a + * component service (or an external service) over the selected binding + * + * @version $Rev: 576055 $ $Date: 2007-09-16 00:11:45 -0700 (Sun, 16 Sep 2007) $ + */ +public interface RuntimeWire extends Cloneable { + + /** + * Get the source of the wire + * + * @return The end point reference of the source + */ + EndpointReference getSource(); + + /** + * Get the target of the wire + * + * @return The end point reference of the target + */ + EndpointReference getTarget(); + + /** + * Rebind the runtime wire with the given target + * @param target The target endpoint reference + */ + void setTarget(EndpointReference target); + + /** + * Force the invocation chains to be rebuilt + */ + void rebuild(); + + /** + * Returns the invocation chains for service operations associated with the + * wire + * + * @return the invocation chains for service operations associated with the + * wire + */ + List getInvocationChains(); + + /** + * Lookup the invocation chain by operation + * @param operation The operation + * @return The invocation chain for the given operation + */ + InvocationChain getInvocationChain(Operation operation); + + /** + * Invoke an operation with given arguments + * @param operation The operation + * @param args The arguments + * @return The result + * @throws InvocationTargetException + */ + Object invoke(Operation operation, Object[] args) throws InvocationTargetException; + + /** + * Invoke an operation with a context message + * @param operation The operation + * @param msg The message + * @return The result + * @throws InvocationTargetException + */ + Object invoke(Operation operation, Message msg) throws InvocationTargetException; + + /** + * @return a clone of the runtime wire + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.java new file mode 100644 index 0000000000..a828995c5a --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.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.runtime; + +/** + * Implementations are called after wires are decorated with policy and before they are connected. + * + * @version $Rev: 538423 $ $Date: 2007-05-15 21:11:06 -0700 (Tue, 15 May 2007) $ + */ +public interface RuntimeWireProcessor { + + /** + * Process the runtime wire to add interceptors + * + * @param wire + */ + void process(RuntimeWire wire); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.java new file mode 100644 index 0000000000..30630cc2af --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.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.runtime; + +import java.util.List; + +/** + * Acts as a delegating WireProcessorExtensionPoint, delegating + * processing of wires after policies have been applied and source and targets + * have been connected. + * + * @version $Rev: 539355 $ $Date: 2007-05-18 03:05:14 -0700 (Fri, 18 May 2007) $ + */ +public interface RuntimeWireProcessorExtensionPoint { + + /** + * Registers a wire-processor in the runtime + * + * @param processor The processor to register + */ + void addWireProcessor(RuntimeWireProcessor processor); + + /** + * De-registers a wire-processor in the runtime + * + * @param processor The processor to de-register + */ + void removeWireProcessor(RuntimeWireProcessor processor); + + /** + * Returns a list of registered wire-processors. + * + * @return The list of wire processors + */ + List getWireProcessors(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/DuplicateRecordException.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/DuplicateRecordException.java new file mode 100644 index 0000000000..465b385d57 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/DuplicateRecordException.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.store; + +/** + * thrown when a record already exists during an insert operation + * + * @version $Rev: 537206 $ $Date: 2007-05-11 08:14:19 -0700 (Fri, 11 May 2007) $ + */ +public class DuplicateRecordException extends StoreWriteException { + private static final long serialVersionUID = 3116253222569378447L; + + public DuplicateRecordException() { + super(); + } + + public DuplicateRecordException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateRecordException(String message) { + super(message); + } + + public DuplicateRecordException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/RecoveryListener.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/RecoveryListener.java new file mode 100644 index 0000000000..728faf5d0c --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/RecoveryListener.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.store; + +import java.util.UUID; + +/** + * Implementations receive callback events during a store recovery operation + * + * @version $Rev: 537206 $ $Date: 2007-05-11 08:14:19 -0700 (Fri, 11 May 2007) $ + */ +public interface RecoveryListener { + + /** + * Signals the start of a recovery + */ + void onBegin(); + + /** + * Received when a record is recovered + * + * @param id + */ + void onRecord(UUID id); + + /** + * Signals the end of recovery + */ + void onEnd(); +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/Store.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/Store.java new file mode 100644 index 0000000000..45bce4d8fb --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/Store.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.store; + +import org.apache.tuscany.sca.event.EventPublisher; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Implementations provide a persistent store for runtime data such as conversational state. A persistent store could be + * implemented in a durable fashion using JDBC or a journaling system, or using a non-durable mechanism such as an + * in-memory map. + * + * @version $Rev: 538423 $ $Date: 2007-05-15 21:11:06 -0700 (Tue, 15 May 2007) $ + */ +public interface Store extends EventPublisher { + + /* Used to indicate an the default expiration offset for records for the store */ + long DEFAULT_EXPIRATION_OFFSET = -1; + + /* Used to indicate an entry should not expire */ + long NEVER = -2; + + /** + * Adds the given record to the store. Implementations may choose different strategies for writing data such as + * write-through or write-behind. + * + * @param owner the instance owner + * @param id the unique id of the record + * @param object the object representing the data to write + * @param expiration the time in milliseconds when the entry expires + * @throws StoreWriteException if an error occurs during the write operation + */ + void insertRecord(RuntimeComponent owner, String id, Object object, long expiration) throws StoreWriteException; + + /** + * Updates a given record in the store, overwriting previous information. + * + * @param owner the instance owner + * @param id the unique id of the record + * @param object the object representing the data to write + * @param expiration the time in milliseconds when the entry expires + * @throws StoreWriteException + */ + void updateRecord(RuntimeComponent owner, String id, Object object, long expiration) throws StoreWriteException; + + /** + * Returns the deserialized object in the store corresponding to the given id + * + * @param owner the instance owner + * @param id the unique id of the record + * @return the deserialized object or null if one is not found + * @throws StoreReadException + */ + Object readRecord(RuntimeComponent owner, String id) throws StoreReadException; + + /** + * Removes a record from the store + * + * @param owner the instance owner + * @param id the unique id of the record + * @throws StoreWriteException + */ + void removeRecord(RuntimeComponent owner, String id) throws StoreWriteException; + + /** + * Removes all records from the store + * + * @throws StoreWriteException + */ + void removeRecords() throws StoreWriteException; + + /** + * Initiates a recovery operation, for example during restart after a crash + * + * @param listener the listener to receive recovery callback events + * @throws StoreReadException + */ + void recover(RecoveryListener listener) throws StoreReadException; + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreException.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreException.java new file mode 100644 index 0000000000..24f8c1a8fd --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreException.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.store; + + +/** + * Represents a generic exception thrown by a Store + * + * @version $Rev: 537206 $ $Date: 2007-05-11 08:14:19 -0700 (Fri, 11 May 2007) $ + */ +public class StoreException extends Exception { + private static final long serialVersionUID = -319152147419962709L; + + public StoreException() { + super(); + } + + public StoreException(String message, Throwable cause) { + super(message, cause); + } + + public StoreException(String message) { + super(message); + } + + public StoreException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreExpirationEvent.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreExpirationEvent.java new file mode 100644 index 0000000000..8798f31138 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreExpirationEvent.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.store; + +import org.apache.tuscany.sca.event.Event; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Fired when a store implementation expires a resource + * + * @version $Rev: 538423 $ $Date: 2007-05-15 21:11:06 -0700 (Tue, 15 May 2007) $ + */ +public class StoreExpirationEvent implements Event { + private Object source; + private RuntimeComponent owner; + private Object instance; + + /** + * Constructor. + * + * @param source the source of the event + * @param owner the owner of the expiring object + * @param instance the expiring object + */ + public StoreExpirationEvent(Object source, RuntimeComponent owner, Object instance) { + assert source != null; + assert owner != null; + assert instance != null; + this.source = source; + this.owner = owner; + this.instance = instance; + } + + public Object getSource() { + return source; + } + + /** + * Returns the owner of the expiring object. + * + * @return the owner of the expiring object. + */ + public RuntimeComponent getOwner() { + return owner; + } + + /** + * Returns the expiring object. + * + * @return the expiring object. + */ + public Object getInstance() { + return instance; + } +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreMonitor.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreMonitor.java new file mode 100644 index 0000000000..7cbf4c5ea6 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreMonitor.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.store; + + +/** + * A generic monitor interface for services to log events + * + * @version $Rev: 639280 $ $Date: 2008-03-20 06:10:11 -0700 (Thu, 20 Mar 2008) $ + */ +public interface StoreMonitor { + + /** + * Signals the service has started + * + * @param msg + */ + void start(String msg); + + /** + * Signals the service has been shutdown + * + * @param msg + */ + void stop(String msg); + + /** + * Fired when recovery is started + */ + + void beginRecover(); + + /** + * Fired when recovery is completed + */ + + void endRecover(); + + /** + * Fired when a record is processed during recovery + * + * @param recordId the id of the record being recovered + */ + + void recover(Object recordId); + + /** + * Signals an error event + * + * @param e the error + */ + + void error(Throwable e); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreReadException.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreReadException.java new file mode 100644 index 0000000000..9e05090845 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreReadException.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.store; + +/** + * Thrown when an error occurs reading from persistent storage + * + * @version $Rev: 537206 $ $Date: 2007-05-11 08:14:19 -0700 (Fri, 11 May 2007) $ + */ +public class StoreReadException extends StoreException { + private static final long serialVersionUID = -8624542082121467271L; + + public StoreReadException() { + super(); + } + + public StoreReadException(String message, Throwable cause) { + super(message, cause); + } + + public StoreReadException(String message) { + super(message); + } + + public StoreReadException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreWriteException.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreWriteException.java new file mode 100644 index 0000000000..024c3af2f0 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/store/StoreWriteException.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.store; + +/** + * Thrown when an error occurs writing to persistent storage + * + * @version $Rev: 537206 $ $Date: 2007-05-11 08:14:19 -0700 (Fri, 11 May 2007) $ + */ +public class StoreWriteException extends StoreException { + private static final long serialVersionUID = 5539070473942048555L; + + public StoreWriteException() { + super(); + } + + public StoreWriteException(String message, Throwable cause) { + super(message, cause); + } + + public StoreWriteException(String message) { + super(message); + } + + public StoreWriteException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.java new file mode 100644 index 0000000000..668866113e --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.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.work; + +/** + * A callback interface that can be optionally used for registering + * interest in status of asynchronously scheduled unit of work. + * + */ +public interface NotificationListener { + + /** + * Callback method when the unit of work is accepted. + * + * @param work Work that was accepted. + */ + void workAccepted(T work); + + /** + * Callback method when the unit of work is successfully completed. + * + * @param work Work that was successfully completed. + */ + void workCompleted(T work); + + /** + * Callback when the unit of work is started. + * + * @param work Unit of work that was started. + */ + void workStarted(T work); + + /** + * Callback when the unit of work is rejected. + * + * @param work Unit of work that was rejected. + */ + void workRejected(T work); + + /** + * Callback when the unit of work fails to complete. + * + * @param work Unit of work that failed to complete. + * @param error Error that caused the unit of work to fail. + */ + void workFailed(T work, Throwable error); + + + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java new file mode 100644 index 0000000000..fd0ed52752 --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.work; + +/** + * Defines the contract for scheduling asynchronous units of work. + * + *

+ * Units of work can be scheduled with an optional NotificationListener. + * If a notification listener is specified, the caller will be notified regarding the + * status of the work. The unit of work can either be completed, rejected or completed + * with an error. If the work completed with an error, the caller is notified with the + * error details. + *

+ * + */ +public interface WorkScheduler { + + /** + * 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. + */ + void scheduleWork(T work, NotificationListener listener); + + /** + * 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. + */ + void scheduleWork(T work); + + /** + * Destroys the work scheduler + */ + void destroy(); + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.java b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.java new file mode 100644 index 0000000000..5ec6f8299d --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.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.work; + + +/** + * Exception thrown by the work scheduler in case of unexpected exceptions. + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + * + */ +public class WorkSchedulerException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public WorkSchedulerException() { + super(); + } + + public WorkSchedulerException(String message, Throwable cause) { + super(message, cause); + } + + public WorkSchedulerException(String message) { + super(message); + } + + public WorkSchedulerException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint b/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint new file mode 100644 index 0000000000..e9de1f135f --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint @@ -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.provider.DefaultProviderFactoryExtensionPoint diff --git a/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint b/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint new file mode 100644 index 0000000000..2f700671ca --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint @@ -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.provider.DefaultSCADefinitionsProviderExtensionPoint + \ No newline at end of file diff --git a/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint b/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint new file mode 100644 index 0000000000..95591dca5d --- /dev/null +++ b/branches/sca-android/tuscany-core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint @@ -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.runtime.DefaultWireProcessorExtensionPoint diff --git a/branches/sca-android/tuscany-implementation-java-runtime/.classpath b/branches/sca-android/tuscany-implementation-java-runtime/.classpath new file mode 100644 index 0000000000..ae8a04f371 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java-runtime/.project b/branches/sca-android/tuscany-implementation-java-runtime/.project new file mode 100644 index 0000000000..04641c6b07 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/.project @@ -0,0 +1,31 @@ + + tuscany-implementation-java-runtime + Parent POM defining settings that can be used across Tuscany + + tuscany-core-spi + tuscany-extensibility + tuscany-sca-api + tuscany-assembly + tuscany-policy + tuscany-interface + tuscany-definitions + tuscany-contribution + tuscany-databinding + tuscany-core + tuscany-contribution-java + tuscany-interface-java + tuscany-implementation-java + tuscany-implementation-java-xml + tuscany-assembly-xml + tuscany-contribution-namespace + tuscany-interface-java-xml + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java-runtime/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-implementation-java-runtime/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..ef585c634f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:21:26 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-implementation-java-runtime/DISCLAIMER b/branches/sca-android/tuscany-implementation-java-runtime/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-implementation-java-runtime/LICENSE b/branches/sca-android/tuscany-implementation-java-runtime/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/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/branches/sca-android/tuscany-implementation-java-runtime/NOTICE b/branches/sca-android/tuscany-implementation-java-runtime/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-implementation-java-runtime/pom.xml b/branches/sca-android/tuscany-implementation-java-runtime/pom.xml new file mode 100644 index 0000000000..cf450f3fc2 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/pom.xml @@ -0,0 +1,56 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-implementation-java-runtime + Apache Tuscany SCA Java Implementation Model + + + + org.apache.tuscany.sca + tuscany-core-spi + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-implementation-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-implementation-java-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-databinding + 2.0-incubating-SNAPSHOT + + + diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java new file mode 100644 index 0000000000..7f531a7e8a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; + +/** + * Interface for a factory that returns an injected component instance. + * This is used by a Component implementation to create new instances of + * application implementation objects as determined by the component scope's + * lifecycle. + *

+ * The implementation of this interface may be supplied by the user, + * may be generated during deployment, or may be dynamic. + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + * @param Type of the instance generated by the factory. + */ +public interface InstanceFactory { + /** + * Creates a new instance of the component. + * All injected values must be set but any @Init methods must not have been invoked. + * + * @return A wrapper for the created component instance. + */ + InstanceWrapper newInstance(); +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java new file mode 100644 index 0000000000..c1d2a14ddd --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; + +/** + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public interface InstanceFactoryProvider { + /** + * Return the implementation class. + * + * @return the implementation class. + */ + Class getImplementationClass(); + + /** + * Sets an object factory for an injection site + * + * @param element the injection site name + * @param objectFactory the object factory + */ + void setObjectFactory(JavaElementImpl element, ObjectFactory objectFactory); + + /** + * Create an instance factory that can be used to create component instances. + * + * @return a new instance factory + */ + InstanceFactory createFactory(); +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java new file mode 100644 index 0000000000..092736918a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.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.implementation.java.context; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class ReflectiveInstanceFactory implements InstanceFactory { + private final Constructor ctr; + private final ObjectFactory[] ctrArgs; + private final Injector[] injectors; + private final EventInvoker initInvoker; + private final EventInvoker destroyInvoker; + + public ReflectiveInstanceFactory(Constructor ctr, + ObjectFactory[] ctrArgs, + Injector[] injectors, + EventInvoker initInvoker, + EventInvoker destroyInvoker) { + this.ctr = ctr; + this.ctrArgs = ctrArgs; + this.injectors = injectors; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + } + + public InstanceWrapper newInstance() { + T instance; + try { + if (ctrArgs != null) { + Object[] args = new Object[ctrArgs.length]; + for (int i = 0; i < args.length; i++) { + args[i] = ctrArgs[i].getInstance(); + } + instance = ctr.newInstance(args); + } else { + instance = ctr.newInstance(); + } + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch ( + InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } + + if (injectors != null) { + for (Injector injector : injectors) { + //FIXME Injectors should never be null + if (injector != null) + injector.inject(instance); + } + } + + return new ReflectiveInstanceWrapper(instance, initInvoker, destroyInvoker); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java new file mode 100644 index 0000000000..e7a5b3de03 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; +import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class ReflectiveInstanceWrapper implements InstanceWrapper { + private final EventInvoker initInvoker; + private final EventInvoker destroyInvoker; + private final T instance; + + public ReflectiveInstanceWrapper(T instance, EventInvoker initInvoker, EventInvoker destroyInvoker) { + this.instance = instance; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + } + + public T getInstance() { + return instance; + } + + public void start() throws TargetInitializationException { + if (initInvoker != null) { + initInvoker.invokeEvent(instance); + } + } + + + public void stop() throws TargetDestructionException { + if (destroyInvoker != null) { + destroyInvoker.invokeEvent(instance); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java new file mode 100644 index 0000000000..00bcdcbbc1 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Array; +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an Array + * containing object instances + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class ArrayMultiplicityObjectFactory implements ObjectFactory { + + private ObjectFactory[] factories; + + private Class interfaceType; + + public ArrayMultiplicityObjectFactory(Class interfaceType, List> factories) { + assert interfaceType != null : "Interface type was null"; + assert factories != null : "Object factories were null"; + this.interfaceType = interfaceType; + this.factories = factories.toArray(new ObjectFactory[factories.size()]); + } + + public Object getInstance() throws ObjectCreationException { + Object array = Array.newInstance(interfaceType, factories.length); + for (int i = 0; i < factories.length; i++) { + Array.set(array, i, factories[i].getInstance()); + } + return array; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java new file mode 100644 index 0000000000..0c91f31cc2 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + +/** + * Implementations inject a pre-configured context type (interface) on an instance. + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public interface ContextInjector extends Injector { + + void setContext(S context) throws ObjectCreationException; + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.java new file mode 100644 index 0000000000..f326ed4748 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ConversationIDObjectFactory.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.ThreadMessageContext; + +public class ConversationIDObjectFactory implements ObjectFactory { + + public ConversationIDObjectFactory() { + } + + public Object getInstance() { + return ThreadMessageContext.getMessageContext().getFrom().getReferenceParameters().getConversationID(); + + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java new file mode 100644 index 0000000000..a1cfa6c98d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Field; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.sca.core.factory.ObjectFactory} on a given field + * + * @version $Rev: 639649 $ $Date: 2008-03-21 06:04:01 -0800 (Fri, 21 Mar 2008) $ + */ +public class FieldInjector implements Injector { + + private final Field field; + + private final ObjectFactory objectFactory; + + /** + * Create an injector and have it use the given ObjectFactory to inject a value on the instance using + * the reflected Field + */ + public FieldInjector(Field field, ObjectFactory objectFactory) { + this.field = field; + this.field.setAccessible(true); + this.objectFactory = objectFactory; + } + + /** + * Inject a new value on the given instance + */ + public void inject(T instance) throws ObjectCreationException { + try { + field.set(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Field is not accessible [" + field + "]"); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java new file mode 100644 index 0000000000..edd003f196 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.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.implementation.java.injection; + + +/** + * Root unchecked exception for the injection package + * + * @version $Rev: 537424 $ $Date: 2007-05-12 06:47:18 -0700 (Sat, 12 May 2007) $ + */ +public abstract class InjectionRuntimeException extends RuntimeException { + + public InjectionRuntimeException() { + super(); + } + + public InjectionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public InjectionRuntimeException(String message) { + super(message); + } + + public InjectionRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java new file mode 100644 index 0000000000..f1fef2149e --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + +/** + * Implementations inject a pre-configured value on an instance + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public interface Injector { + + /** + * Inject a value on the given instance + */ + void inject(T instance) throws ObjectCreationException; + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java new file mode 100644 index 0000000000..e8bed559d0 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.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.implementation.java.injection; + +/** + * @version $$Rev: 567313 $$ $$Date: 2007-08-18 11:38:44 -0700 (Sat, 18 Aug 2007) $$ + */ +public class InvalidAccessorException extends InjectionRuntimeException { + private static final long serialVersionUID = 9196299279363310978L; + + public InvalidAccessorException() { + super(); + } + + public InvalidAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidAccessorException(String message) { + super(message); + } + + public InvalidAccessorException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java new file mode 100644 index 0000000000..0b97f3eb8b --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java @@ -0,0 +1,293 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.xml.DOMDataBinding; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class JavaPropertyValueObjectFactory implements PropertyValueFactory { + private Mediator mediator = null; + private boolean isSimpleType; + + public JavaPropertyValueObjectFactory(Mediator mediator) { + this.mediator = mediator; + } + + public ObjectFactory createValueFactory(Property property, Object propertyValue, JavaElementImpl javaElement) { + isSimpleType = isSimpleType(property); + Document doc = (Document)propertyValue; + Class javaType = JavaIntrospectionHelper.getBaseType(javaElement.getType(), javaElement.getGenericType()); + Element rootElement = doc.getDocumentElement(); + if (property.isMany()) { + if (isSimpleType) { + String value = ""; + if (rootElement.getChildNodes().getLength() > 0) { + value = rootElement.getChildNodes().item(0).getTextContent(); + } + List values = getSimplePropertyValues(value, javaType); + if ( javaElement.getType().isArray() ) { + return new ArrayObjectFactoryImpl(property, values, isSimpleType, javaType); + } else { + return new ListObjectFactoryImpl(property, values, isSimpleType, javaType); + } + } else { + if ( javaElement.getType().isArray() ) { + return new ArrayObjectFactoryImpl(property, getComplexPropertyValues(doc), isSimpleType, javaType); + } else { + return new ListObjectFactoryImpl(property, getComplexPropertyValues(doc), isSimpleType, javaType); + } + } + } else { + if (isSimpleType) { + String value = ""; + if (rootElement.getChildNodes().getLength() > 0) { + value = rootElement.getChildNodes().item(0).getTextContent(); + } + return new ObjectFactoryImpl(property, value, isSimpleType, javaType); + } else { + List nodes = getComplexPropertyValues(doc); + Object value = null; + if (!nodes.isEmpty()) { + value = nodes.get(0); + } + return new ObjectFactoryImpl(property, value, isSimpleType, javaType); + } + + } + } + + public ObjectFactory createValueFactory(Property property, Object propertyValue, Class javaType) { + isSimpleType = isSimpleType(property); + Document doc = (Document)propertyValue; + Element rootElement = doc.getDocumentElement(); + if (property.isMany()) { + if (isSimpleType) { + String value = ""; + if (rootElement.getChildNodes().getLength() > 0) { + value = rootElement.getChildNodes().item(0).getTextContent(); + } + List values = getSimplePropertyValues(value, javaType); + return new ListObjectFactoryImpl(property, values, isSimpleType, javaType); + } else { + return new ListObjectFactoryImpl(property, getComplexPropertyValues(doc), isSimpleType, javaType); + } + } else { + if (isSimpleType) { + String value = ""; + if (rootElement.getChildNodes().getLength() > 0) { + value = rootElement.getChildNodes().item(0).getTextContent(); + } + return new ObjectFactoryImpl(property, value, isSimpleType, javaType); + } else { + List nodes = getComplexPropertyValues(doc); + Object value = null; + if (!nodes.isEmpty()) { + value = nodes.get(0); + } + return new ObjectFactoryImpl(property, value, isSimpleType, javaType); + } + + } + } + + private boolean isSimpleType(Property property) { + if (property.getXSDType() != null) { + return SimpleTypeMapperImpl.isSimpleXSDType(property.getXSDType()); + } else { + if (property instanceof Document) { + Document doc = (Document)property; + Element element = doc.getDocumentElement(); + if (element.getChildNodes().getLength() == 1 && element.getChildNodes().item(0).getNodeType() == Element.TEXT_NODE) { + return true; + } + } + } + return false; + } + + private List getSimplePropertyValues(String concatenatedValue, Class javaType) { + List propValues = new ArrayList(); + StringTokenizer st = null; + if (javaType.getName().equals("java.lang.String")) { + st = new StringTokenizer(concatenatedValue, "\""); + } else { + st = new StringTokenizer(concatenatedValue); + } + String aToken = null; + while (st.hasMoreTokens()) { + aToken = st.nextToken(); + if (aToken.trim().length() > 0) { + propValues.add(aToken); + } + } + return propValues; + } + + private List getComplexPropertyValues(Document document) { + Element rootElement = document.getDocumentElement(); + List propValues = new ArrayList(); + NodeList nodes = rootElement.getChildNodes(); + for (int count = 0; count < nodes.getLength(); ++count) { + if (nodes.item(count).getNodeType() == Document.ELEMENT_NODE) { + propValues.add(DOMHelper.promote(nodes.item(count))); + } + } + return propValues; + } + + public abstract class ObjectFactoryImplBase implements ObjectFactory { + protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl(); + protected Property property; + protected Object propertyValue; + protected Class javaType; + protected DataType sourceDataType; + protected DataType targetDataType; + boolean isSimpleType; + + public ObjectFactoryImplBase(Property property, Object propertyValue, boolean isSimpleType, Class javaType) { + this.isSimpleType = isSimpleType; + this.property = property; + this.propertyValue = propertyValue; + this.javaType = javaType; + sourceDataType = new DataTypeImpl(DOMDataBinding.NAME, Node.class, new XMLType(null, this.property + .getXSDType())); + TypeInfo typeInfo = null; + if (this.property.getXSDType() != null) { + if (SimpleTypeMapperImpl.isSimpleXSDType(this.property.getXSDType())) { + typeInfo = new TypeInfo(property.getXSDType(), true, null); + } else { + typeInfo = new TypeInfo(property.getXSDType(), false, null); + } + } else { + typeInfo = new TypeInfo(property.getXSDType(), false, null); + } + + XMLType xmlType = new XMLType(typeInfo); + String dataBinding = null; // (String)property.getExtensions().get(DataBinding.class.getName()); + if (dataBinding != null) { + targetDataType = new DataTypeImpl(dataBinding, javaType, xmlType); + } else { + targetDataType = new DataTypeImpl(dataBinding, javaType, xmlType); + mediator.getDataBindings().introspectType(targetDataType, null); + } + } + } + + public class ObjectFactoryImpl extends ObjectFactoryImplBase { + public ObjectFactoryImpl(Property property, Object propertyValue, boolean isSimpleType, Class javaType) { + super(property, propertyValue, isSimpleType, javaType); + } + + @SuppressWarnings("unchecked") + public Object getInstance() throws ObjectCreationException { + if (isSimpleType) { + return simpleTypeMapper.toJavaObject(property.getXSDType(), (String)propertyValue, null); + } else { + return mediator.mediate(propertyValue, sourceDataType, targetDataType, null); + // return null; + } + } + } + + public class ListObjectFactoryImpl extends ObjectFactoryImplBase { + public ListObjectFactoryImpl(Property property, List propertyValues, boolean isSimpleType, Class javaType) { + super(property, propertyValues, isSimpleType, javaType); + } + + @SuppressWarnings("unchecked") + public List getInstance() throws ObjectCreationException { + if (isSimpleType) { + List values = new ArrayList(); + for (String aValue : (List)propertyValue) { + values.add(simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null)); + } + return values; + } else { + List instances = new ArrayList(); + for (Node aValue : (List)propertyValue) { + instances.add(mediator.mediate(aValue, sourceDataType, targetDataType, null)); + } + return instances; + } + } + } + + public class ArrayObjectFactoryImpl extends ObjectFactoryImplBase { + public ArrayObjectFactoryImpl(Property property, List propertyValues, boolean isSimpleType, Class javaType) { + super(property, propertyValues, isSimpleType, javaType); + } + + @SuppressWarnings("unchecked") + public Object getInstance() throws ObjectCreationException { + if (isSimpleType) { + int count = 0; + Object values = Array.newInstance(javaType, ((List)propertyValue).size()); + for (String aValue : (List)propertyValue) { + Array.set(values, count++, simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null)); + } + return values; + } else { + Object instances = Array.newInstance(javaType, ((List)propertyValue).size()); + int count = 0; + for (Node aValue : (List)propertyValue) { + Array.set(instances, count++, mediator.mediate(aValue, sourceDataType, targetDataType, null)); + } + return instances; + } + } + } + + /** + * This method will create an instance of the value for the specified Property. + * + * @param property The Property from which to retrieve the property value + * @param type The type of the property value being retrieved from the Property + * @param Type type of the property value being looked up + * + * @return the value for the Property + */ + public B createPropertyValue(ComponentProperty property, Class type) + { + ObjectFactory factory = this.createValueFactory(property, property.getValue(), type); + return factory.getInstance(); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java new file mode 100644 index 0000000000..89c845cd00 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an List + * containing object instances + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class ListMultiplicityObjectFactory implements ObjectFactory { + + private ObjectFactory[] factories; + + public ListMultiplicityObjectFactory(List> factories) { + assert factories != null : "Object factories were null"; + this.factories = factories.toArray(new ObjectFactory[factories.size()]); + } + + public List getInstance() throws ObjectCreationException { + List list = new ArrayList(); + for (ObjectFactory factory : factories) { + list.add(factory.getInstance()); + } + return list; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java new file mode 100644 index 0000000000..947db7110d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.sca.core.factory.ObjectFactory} using a given method + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +public class MethodInjector implements Injector { + private final Method method; + private final ObjectFactory objectFactory; + + public MethodInjector(Method aMethod, ObjectFactory objectFactory) { + assert aMethod != null; + assert objectFactory != null; + this.method = aMethod; + // Allow privileged access to set accessibility. Requires ReflectPermission in security + // policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + method.setAccessible(true); + return null; + } + }); + this.objectFactory = objectFactory; + } + + public void inject(T instance) throws ObjectCreationException { + try { + method.invoke(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (IllegalArgumentException e) { + throw new ObjectCreationException("Exception thrown by setter: " + method.getName(), e); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by setter: " + method.getName(), e); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java new file mode 100644 index 0000000000..df71a24a07 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.context.RequestContextImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.osoa.sca.RequestContext; + +/** + * Creates instances of + * {@link org.apache.tuscany.sca.core.context.RequestContextImpl} for + * injection on component implementation instances + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class RequestContextObjectFactory implements ObjectFactory { + private RequestContextFactory factory; + private ProxyFactory proxyFactory; + + public RequestContextObjectFactory(RequestContextFactory factory) { + this(factory, null); + } + + public RequestContextObjectFactory(RequestContextFactory factory, ProxyFactory proxyFactory) { + this.factory = factory; + this.proxyFactory = proxyFactory; + } + + public RequestContext getInstance() throws ObjectCreationException { + if (factory != null) { + return factory.createRequestContext(); + } else { + return new RequestContextImpl(proxyFactory); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java new file mode 100644 index 0000000000..e8391f9e90 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +/** + * Interface implemented by host environments that allow for resolution of component implementation resources, e.g. + * items bound in a JNDI tree. + * + * @version $Rev: 537424 $ $Date: 2007-05-12 06:47:18 -0700 (Sat, 12 May 2007) $ + */ +public interface ResourceHost { + + /** + * Resolve a resource matching the given type + * + * @param type the type of the resources + * @throws ResourceResolutionException if an error is encountered during resolution + */ + T resolveResource(Class type) throws ResourceResolutionException; + + /** + * Resolve a resource matching the given type and name + * + * @param type the type of the resources + * @param mappedName the mapped name of the resource + * @throws ResourceResolutionException if an error is encountered during resolution + */ + T resolveResource(Class type, String mappedName) throws ResourceResolutionException; + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java new file mode 100644 index 0000000000..4cd1e9fc18 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + +/** + * Denotes an exception thrown when a runtime resource is not found + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class ResourceNotFoundException extends ObjectCreationException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ResourceNotFoundException() { + super(); + } + + public ResourceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceNotFoundException(String message) { + super(message); + } + + public ResourceNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java new file mode 100644 index 0000000000..ae2f71ba12 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.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.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Resolves a runtime resource to be injected on a field or method of a Java component type marked with {@link + * javax.annotation.Resource}. If the mapped name of the resource is an absolute URI such as + * sca://localhost or jndi://localhost the host container namespace is searched; otherwise the + * URI is assumed to be relative and the parent composite is searched. If a mapped name is not provided, i.e. resolution + * is by type, the parent composite is first searched followed by the host namespace. + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class ResourceObjectFactory implements ObjectFactory { + + private Class type; + private String mappedName; + private ResourceHost host; + private boolean optional; + + /** + * Instantiates a factory that resolves resources by type + * + * @param type the type of the resource to inject + * @param optional true if an error should be thrown if the resource is not found + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class type, boolean optional, ResourceHost host) { + this(type, null, optional, host); + } + + /** + * Instantiates a factory that resolves resources by mapped name + * + * @param type the type of the resource to inject + * @param mappedName the resource name + * @param optional true if an error should be thrown if the resource is not found + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class type, String mappedName, boolean optional, ResourceHost host) { + this.type = type; + this.host = host; + this.mappedName = mappedName; + this.optional = optional; + } + + @SuppressWarnings({"unchecked"}) + public T getInstance() throws ObjectCreationException { + try { + T resource; + if (mappedName == null) { + resource = host.resolveResource(type); + if (!optional && resource == null) { + throw new ResourceNotFoundException("Resource not found: " + type.getName()); + } + } else { + resource = host.resolveResource(type, mappedName); + if (!optional && resource == null) { + throw new ResourceNotFoundException("Resource not found: " + mappedName); + } + } + return resource; + } catch (ResourceResolutionException e) { + throw new ObjectCreationException(e); + } + + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java new file mode 100644 index 0000000000..fc33e8a005 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.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.implementation.java.injection; + + +/** + * @version $Rev: 537424 $ $Date: 2007-05-12 06:47:18 -0700 (Sat, 12 May 2007) $ + */ +public class ResourceResolutionException extends Exception { + private static final long serialVersionUID = 13421352711315479L; + + public ResourceResolutionException() { + super(); + } + + public ResourceResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceResolutionException(String message) { + super(message); + } + + public ResourceResolutionException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.java new file mode 100644 index 0000000000..4b6c061cbd --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import org.apache.tuscany.sca.implementation.java.injection.InjectionRuntimeException; + +/** + * Denotes an error when invoking an event on an object + * + * @version $Rev: 567313 $ $Date: 2007-08-18 11:38:44 -0700 (Sat, 18 Aug 2007) $ + */ +public class EventInvocationException extends InjectionRuntimeException { + private static final long serialVersionUID = 1480018831708211581L; + + public EventInvocationException() { + super(); + } + + public EventInvocationException(String message, Throwable cause) { + super(message, cause); + } + + public EventInvocationException(String message) { + super(message); + } + + public EventInvocationException(Throwable cause) { + super(cause); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.java new file mode 100644 index 0000000000..67e161df53 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +/** + * Performs an invocation on an instance + * + * @version $Rev: 567313 $ $Date: 2007-08-18 11:38:44 -0700 (Sat, 18 Aug 2007) $ + */ +public interface EventInvoker { + + /** + * Performs the invocation on a given instance + * + * @throws EventInvocationException + */ + void invokeEvent(T instance) throws EventInvocationException; +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java new file mode 100644 index 0000000000..10a8195742 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import org.apache.tuscany.sca.core.invocation.TargetInvocationException; + +/** + * Denotes an unknown operation sequence in a conversation + * + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class InvalidConversationSequenceException extends TargetInvocationException { + private static final long serialVersionUID = -5744028391493899147L; + + public InvalidConversationSequenceException() { + super(); + } + + public InvalidConversationSequenceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidConversationSequenceException(String message) { + super(message); + } + + public InvalidConversationSequenceException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.java new file mode 100644 index 0000000000..fd6376cd58 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.core.invocation.CallbackInterfaceInterceptor; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +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.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; + +/** + * @version $Rev: 632064 $ $Date: 2008-02-28 09:18:51 -0800 (Thu, 28 Feb 2008) $ + */ +public class JavaCallbackRuntimeWireProcessor implements RuntimeWireProcessor { + private final static Logger logger = Logger.getLogger(JavaCallbackRuntimeWireProcessor.class.getName()); + private InterfaceContractMapper interfaceContractMapper; + private JavaInterfaceFactory javaInterfaceFactory; + + /** + * @param interfaceContractMapper + * @param javaInterfaceFactory + */ + public JavaCallbackRuntimeWireProcessor(InterfaceContractMapper interfaceContractMapper, + JavaInterfaceFactory javaInterfaceFactory) { + super(); + this.interfaceContractMapper = interfaceContractMapper; + this.javaInterfaceFactory = javaInterfaceFactory; + } + + public void process(RuntimeWire wire) { + addCallbackInterfaceInterceptors(wire); + } + + private void addCallbackInterfaceInterceptors(RuntimeWire wire) { + Contract contract = wire.getSource().getContract(); + if (!(contract instanceof RuntimeComponentReference)) { + return; + } + RuntimeComponent component = wire.getSource().getComponent(); + Implementation implementation = component.getImplementation(); + if (!(implementation instanceof JavaImplementation)) { + return; + } + JavaImplementation javaImpl = (JavaImplementation)implementation; + EndpointReference callbackEndpoint = wire.getSource().getCallbackEndpoint(); + if (callbackEndpoint != null) { + Interface iface = callbackEndpoint.getContract().getInterfaceContract().getInterface(); + if (!supportsCallbackInterface(iface, javaImpl)) { + // callback to this impl is not possible, so ensure a callback object is set + for (InvocationChain chain : wire.getInvocationChains()) { + chain.addInterceptor(Phase.REFERENCE, new CallbackInterfaceInterceptor()); + } + } + } + } + + private boolean supportsCallbackInterface(Interface iface, JavaImplementation impl) { + if (iface instanceof JavaInterface) { + Class ifaceClass = ((JavaInterface)iface).getJavaClass(); + if (ifaceClass.isAssignableFrom(impl.getJavaClass())) { + return true; + } + } + try { + Interface implType = javaInterfaceFactory.createJavaInterface(impl.getJavaClass()); + // Ignore the remotable/conversational testing + implType.setRemotable(iface.isRemotable()); + implType.setConversational(iface.isConversational()); + return interfaceContractMapper.isCompatible(iface, implType); + } catch (InvalidInterfaceException e) { + logger.log(Level.WARNING, e.getMessage(), e); + return false; + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.java new file mode 100644 index 0000000000..1ac7859e3e --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.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.implementation.java.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.osoa.sca.ComponentContext; + +/** + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class JavaComponentContextFactory implements ObjectFactory { + private final JavaComponentContextProvider component; + + + public JavaComponentContextFactory(JavaComponentContextProvider component) { + this.component = component; + } + + + public ComponentContext getInstance() throws ObjectCreationException { + return component.getComponent().getComponentContext(); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java new file mode 100644 index 0000000000..f8a9a6b3c4 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java @@ -0,0 +1,379 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.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.Multiplicity; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.context.ComponentContextImpl; +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallableReferenceObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallbackReferenceObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.WireObjectFactory; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.injection.ConversationIDObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.InvalidAccessorException; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.osoa.sca.CallableReference; +import org.osoa.sca.annotations.ConversationID; + +/** + * The runtime instantiation of Java component implementations + * + * @version $Rev: 638895 $ $Date: 2008-03-19 08:56:51 -0700 (Wed, 19 Mar 2008) $ + */ +public class JavaComponentContextProvider { + private JavaPropertyValueObjectFactory propertyValueFactory; + private DataBindingExtensionPoint dataBindingRegistry; + private RuntimeComponent component; + private JavaInstanceFactoryProvider instanceFactoryProvider; + private ProxyFactory proxyFactory; + + public JavaComponentContextProvider(RuntimeComponent component, + JavaInstanceFactoryProvider configuration, + DataBindingExtensionPoint dataBindingExtensionPoint, + JavaPropertyValueObjectFactory propertyValueObjectFactory, + ComponentContextFactory componentContextFactory, + RequestContextFactory requestContextFactory) { + super(); + this.instanceFactoryProvider = configuration; + this.proxyFactory = configuration.getProxyFactory(); + // if (componentContextFactory != null) { + // this.componentContext = componentContextFactory.createComponentContext(component, requestContextFactory); + // } else { + // this.componentContext = new ComponentContextImpl(this, requestContextFactory, this.proxyService); + // } + this.component = component; + this.dataBindingRegistry = dataBindingExtensionPoint; + this.propertyValueFactory = propertyValueObjectFactory; + } + + InstanceWrapper createInstanceWrapper() throws ObjectCreationException { + return instanceFactoryProvider.createFactory().newInstance(); + } + + void configureProperties(List definedProperties) { + for (ComponentProperty p : definedProperties) { + configureProperty(p); + } + } + + private void configureProperty(ComponentProperty configuredProperty) { + JavaElementImpl element = + instanceFactoryProvider.getImplementation().getPropertyMembers().get(configuredProperty.getName()); + + if (element != null && configuredProperty.getValue() != null) { + if (!(element.getAnchor() instanceof Constructor)) { + instanceFactoryProvider.getInjectionSites().add(element); + } + + //Class propertyJavaType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + ObjectFactory propertyObjectFactory = + createPropertyValueFactory(configuredProperty, configuredProperty.getValue(), element); + instanceFactoryProvider.setObjectFactory(element, propertyObjectFactory); + + JavaConstructorImpl constructor = instanceFactoryProvider.getImplementation().getConstructor(); + for(JavaElementImpl p: constructor.getParameters()){ + if(element.getName().equals(p.getName())) { + instanceFactoryProvider.setObjectFactory(p, propertyObjectFactory); + } + } + } + } + + void start() { + if (!instanceFactoryProvider.getImplementation().getCallbackMembers().isEmpty()) { + Map> callbackWires = new HashMap>(); + for (ComponentService service : component.getServices()) { + + RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference(); + if (callbackReference != null) { + List wires = callbackReference.getRuntimeWires(); + if (!wires.isEmpty()) { + callbackWires.put(wires.get(0).getSource().getInterfaceContract().getInterface().toString(), + wires); + } + } + } + + for (Map.Entry entry : instanceFactoryProvider.getImplementation() + .getCallbackMembers().entrySet()) { + List wires = callbackWires.get(entry.getKey()); + if (wires == null) { + // this can happen when there are no client wires to a + // component that has a callback + continue; + } + JavaElementImpl element = entry.getValue(); + Class businessInterface = element.getType(); + ObjectFactory factory = null; + if (CallableReference.class.isAssignableFrom(element.getType())) { + businessInterface = + JavaIntrospectionHelper.getBusinessInterface(element.getType(), element.getGenericType()); + factory = + new CallbackReferenceObjectFactory(businessInterface, proxyFactory, wires); + } else { + factory = new CallbackWireObjectFactory(businessInterface, proxyFactory, wires); + } + if (!(element.getAnchor() instanceof Constructor)) { + instanceFactoryProvider.getInjectionSites().add(element); + } + instanceFactoryProvider.setObjectFactory(element, factory); + } + } + for (Reference ref : instanceFactoryProvider.getImplementation().getReferences()) { + JavaElementImpl element = + instanceFactoryProvider.getImplementation().getReferenceMembers().get(ref.getName()); + if (element != null) { + if (!(element.getAnchor() instanceof Constructor)) { + instanceFactoryProvider.getInjectionSites().add(element); + } + ComponentReference componentReference = null; + List wireList = null; + for (ComponentReference reference : component.getReferences()) { + if (reference.getName().equals(ref.getName())) { + wireList = ((RuntimeComponentReference)reference).getRuntimeWires(); + componentReference = reference; + break; + } + } + if (ref.getMultiplicity() == Multiplicity.ONE_N || ref.getMultiplicity() == Multiplicity.ZERO_N) { + List> factories = new ArrayList>(); + Class baseType = + JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + for (int i = 0; i < wireList.size(); i++) { + ObjectFactory factory = null; + if (CallableReference.class.isAssignableFrom(baseType)) { + Type callableRefType = JavaIntrospectionHelper.getParameterType(element.getGenericType()); + // Type businessType = JavaIntrospectionHelper.getParameterType(callableRefType); + Class businessInterface = + JavaIntrospectionHelper.getBusinessInterface(baseType, callableRefType); + factory = + new CallableReferenceObjectFactory(businessInterface, component, + (RuntimeComponentReference)wireList.get(i) + .getSource().getContract(), wireList.get(i) + .getSource().getBinding()); + } else { + factory = createObjectFactory(baseType, wireList.get(i)); + } + factories.add(factory); + } + instanceFactoryProvider.setObjectFactories(element, factories); + JavaConstructorImpl constructor = instanceFactoryProvider.getImplementation().getConstructor(); + for(JavaElementImpl p: constructor.getParameters()){ + if(element.getName().equals(p.getName())) { + instanceFactoryProvider.setObjectFactories(p, factories); + } + } + } else { + if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) { + throw new IllegalStateException("Required reference is missing: " + ref.getName()); + } + if (wireList != null && !wireList.isEmpty()) { + ObjectFactory factory = null; + if (CallableReference.class.isAssignableFrom(element.getType())) { + Class businessInterface = + JavaIntrospectionHelper.getBusinessInterface(element.getType(), element + .getGenericType()); + factory = + new CallableReferenceObjectFactory(businessInterface, component, + (RuntimeComponentReference)componentReference, null); + } else { + factory = createObjectFactory(element.getType(), wireList.get(0)); + } + instanceFactoryProvider.setObjectFactory(element, factory); + JavaConstructorImpl constructor = instanceFactoryProvider.getImplementation().getConstructor(); + for(JavaElementImpl p: constructor.getParameters()){ + if(element.getName().equals(p.getName())) { + instanceFactoryProvider.setObjectFactory(p, factory); + } + } + } + } + } + } + + // We need to set the PropertyValueFactory on the ComponentContextImpl + // so the ComponentContext can "de-marshal" the property type to a value + // when the getProperty() method is called + ComponentContextImpl ccImpl = (ComponentContextImpl)component.getComponentContext(); + ccImpl.setPropertyValueFactory(propertyValueFactory); + + //setUpPolicyHandlers(); + } + + void addResourceFactory(String name, ObjectFactory factory) { + JavaResourceImpl resource = instanceFactoryProvider.getImplementation().getResources().get(name); + + if (resource != null && !(resource.getElement().getAnchor() instanceof Constructor)) { + instanceFactoryProvider.getInjectionSites().add(resource.getElement()); + } + + instanceFactoryProvider.setObjectFactory(resource.getElement(), factory); + } + + void addConversationIDFactories(List names) { + ObjectFactory factory = new ConversationIDObjectFactory(); + for (Member name : names) { + if (name instanceof Field) { + JavaElementImpl element = new JavaElementImpl((Field)name); + element.setClassifer(ConversationID.class); + instanceFactoryProvider.setObjectFactory(element, factory); + } else if (name instanceof Method) { + JavaElementImpl element = new JavaElementImpl((Method)name, 0); + element.setName(JavaIntrospectionHelper.toPropertyName(name.getName())); + element.setClassifer(ConversationID.class); + instanceFactoryProvider.setObjectFactory(element, factory); + } else { + throw new InvalidAccessorException("Member must be a field or method: " + name.getName()); + } + } + } + + Object createInstance() throws ObjectCreationException { + return createInstanceWrapper().getInstance(); + } + + JavaInstanceFactoryProvider getInstanceFactoryProvider() { + return instanceFactoryProvider; + } + + void stop() { + //cleanUpPolicyHandlers(); + } + + Invoker createInvoker(Operation operation) throws NoSuchMethodException { + Class implClass = instanceFactoryProvider.getImplementationClass(); + + Method method = JavaInterfaceUtil.findMethod(implClass, operation); + return new JavaImplementationInvoker(operation, method, component); + } + + private static class OptimizedObjectFactory implements ObjectFactory { + private ScopeContainer scopeContainer; + + public OptimizedObjectFactory(ScopeContainer scopeContainer) { + super(); + this.scopeContainer = scopeContainer; + } + + public T getInstance() throws ObjectCreationException { + try { + return (T)scopeContainer.getWrapper(null).getInstance(); + } catch (TargetResolutionException e) { + throw new ObjectCreationException(e); + } + } + + } + + private ObjectFactory createObjectFactory(Class interfaze, RuntimeWire wire) { + // FIXME: [rfeng] Disable the optimization for new as it needs more discussions + /* + boolean conversational = wire.getSource().getInterfaceContract().getInterface().isConversational(); + Binding binding = wire.getSource().getBinding(); + // Check if it's wireable binding for optimization + if (!conversational && binding instanceof OptimizableBinding) { + OptimizableBinding optimizableBinding = (OptimizableBinding)binding; + Component component = optimizableBinding.getTargetComponent(); + if (component != null) { + Implementation implementation = component.getImplementation(); + // Check if the target component is java component + if (implementation instanceof JavaImplementation) { + JavaImplementation javaImplementation = (JavaImplementation)implementation; + if (interfaze.isAssignableFrom(javaImplementation.getJavaClass())) { + ScopedRuntimeComponent scopedComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = scopedComponent.getScopeContainer(); + Scope scope = scopeContainer.getScope(); + if (scope == Scope.COMPOSITE || scope == Scope.STATELESS || scope == Scope.SYSTEM) { + boolean optimizable = true; + for (InvocationChain chain : wire.getInvocationChains()) { + if (chain.getHeadInvoker() != chain.getTailInvoker()) { + optimizable = false; + break; + } + } + if (optimizable) { + return new OptimizedObjectFactory(scopeContainer); + } + } + } + } + } + } + */ + return new WireObjectFactory(interfaze, wire, proxyFactory); + } + + private ObjectFactory createPropertyValueFactory(ComponentProperty property, + Object propertyValue, + JavaElementImpl javaElement) { + return propertyValueFactory.createValueFactory(property, propertyValue, javaElement); + } + + /** + * @return the component + */ + RuntimeComponent getComponent() { + return component; + } + + /*private void setUpPolicyHandlers() { + for (PolicyHandler policyHandler : policyHandlers.values()) { + policyHandler.setUp(component.getImplementation()); + } + } + + private void cleanUpPolicyHandlers() { + for (PolicyHandler policyHandler : policyHandlers.values() ) { + policyHandler.cleanUp(this); + } + }*/ + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.java new file mode 100644 index 0000000000..fd569e43aa --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.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.implementation.java.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class JavaComponentNameFactory implements ObjectFactory { + private final JavaComponentContextProvider componentContextProvider; + + + public JavaComponentNameFactory(JavaComponentContextProvider component) { + this.componentContextProvider = component; + } + + + public String getInstance() throws ObjectCreationException { + String uri = componentContextProvider.getComponent().getURI(); + return uri.substring(uri.lastIndexOf('/')+1); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java new file mode 100644 index 0000000000..a6206ec0f8 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +import org.apache.tuscany.sca.runtime.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Responsible for synchronously dispatching an invocation to a Java component + * implementation instance + * + * @version $Rev: 634778 $ $Date: 2008-03-07 10:58:16 -0800 (Fri, 07 Mar 2008) $ + */ +public class JavaImplementationInvoker implements Invoker, DataExchangeSemantics { + protected Operation operation; + protected Method method; + protected boolean allowsPBR; + + @SuppressWarnings("unchecked") + protected final ScopeContainer scopeContainer; + + public JavaImplementationInvoker(Operation operation, Method method, RuntimeComponent component) { + assert method != null : "Operation method cannot be null"; + this.method = method; + this.operation = operation; + this.scopeContainer = ((ScopedRuntimeComponent)component).getScopeContainer(); + this.allowsPBR = ((JavaImplementation)component.getImplementation()).isAllowsPassByReference(method); + } + + @SuppressWarnings("unchecked") + public Message invoke(Message msg) { + Operation op = msg.getOperation(); + if (op == null) { + op = this.operation; + } + ConversationSequence sequence = op.getConversationSequence(); + Object payload = msg.getBody(); + + Object contextId = null; + + EndpointReference from = msg.getFrom(); + ReferenceParameters parameters = null; + if (from != null) { + parameters = from.getReferenceParameters(); + } + // check what sort of context is required + if (scopeContainer != null) { + Scope scope = scopeContainer.getScope(); + if (scope == Scope.REQUEST) { + contextId = Thread.currentThread(); + } else if (scope == Scope.CONVERSATION && parameters != null) { + contextId = parameters.getConversationID(); + } + } + + try { + // The following call might create a new conversation, as a result, the msg.getConversationID() might + // return a new value + InstanceWrapper wrapper = scopeContainer.getWrapper(contextId); + + // detects whether the scope container has created a conversation Id. This will + // happen in the case that the component has conversational scope but only the + // callback interface is conversational. Or in the callback case if the service interface + // is conversational and the callback interface isn't. If we are in this situation we need + // to get the contextId of this component and remove it after we have invoked the method on + // it. It is possible that the component instance will not go away when it is removed below + // because a callback conversation will still be holding a reference to it + boolean removeTemporaryConversationalComponentAfterCall = false; + if (parameters != null && (contextId == null) && (parameters.getConversationID() != null)) { + contextId = parameters.getConversationID(); + removeTemporaryConversationalComponentAfterCall = true; + } + + Object instance = wrapper.getInstance(); + Object ret; + if (payload != null && !payload.getClass().isArray()) { + ret = method.invoke(instance, payload); + } else { + ret = method.invoke(instance, (Object[])payload); + } + + scopeContainer.returnWrapper(wrapper, contextId); + + if ((sequence == ConversationSequence.CONVERSATION_END) || (removeTemporaryConversationalComponentAfterCall)) { + // if end conversation, or we have the special case where a conversational + // object was created to service the stateless half of a stateful component + scopeContainer.remove(contextId); + parameters.setConversationID(null); + } + msg.setBody(ret); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } catch (Exception e) { + msg.setFaultBody(e); + } + return msg; + } + + public boolean allowsPassByReference() { + return allowsPBR; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java new file mode 100644 index 0000000000..406c95524f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.context.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.RequestContextObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.ResourceHost; +import org.apache.tuscany.sca.implementation.java.injection.ResourceObjectFactory; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.RequestContext; + +/** + * @version $Rev: 638895 $ $Date: 2008-03-19 08:56:51 -0700 (Wed, 19 Mar 2008) $ + */ +public class JavaImplementationProvider implements ScopedImplementationProvider { + private JavaImplementation implementation; + private JavaComponentContextProvider componentContextProvider; + private RequestContextFactory requestContextFactory; + + public JavaImplementationProvider(RuntimeComponent component, + JavaImplementation implementation, + ProxyFactory proxyService, + DataBindingExtensionPoint dataBindingRegistry, + JavaPropertyValueObjectFactory propertyValueObjectFactory, + ComponentContextFactory componentContextFactory, + RequestContextFactory requestContextFactory, + Map> policyHandlerClassNames) { + super(); + this.implementation = implementation; + this.requestContextFactory = requestContextFactory; + this.implementation.setPolicyHandlerClassNames(policyHandlerClassNames); + + try { + JavaInstanceFactoryProvider configuration = new JavaInstanceFactoryProvider(implementation); + configuration.setProxyFactory(proxyService); + componentContextProvider = + new JavaComponentContextProvider(component, + configuration, + dataBindingRegistry, + propertyValueObjectFactory, + componentContextFactory, + requestContextFactory); + + Scope scope = getScope(); + + if (scope == Scope.SYSTEM || scope == Scope.COMPOSITE) { + // Nothing + } else { + // Check for conversational contract if conversational scope + if (scope == Scope.CONVERSATION) { + boolean hasConversationalContract = false; + for (Service serviceDef : implementation.getServices()) { + if (serviceDef.getInterfaceContract().getInterface().isConversational()) { + hasConversationalContract = true; + break; + } + } + if (!hasConversationalContract) { + String name = implementation.getJavaClass().getName(); + throw new NoConversationalContractException(name); + } + } + } + + if (implementation.getConversationIDMembers().size() > 0) { + componentContextProvider.addConversationIDFactories(implementation.getConversationIDMembers()); + } + + componentContextProvider.configureProperties(component.getProperties()); + handleResources(implementation, proxyService); + } catch (Exception e) { + throw new IllegalStateException(e); + } + + } + + private void handleResources(JavaImplementation componentType, ProxyFactory proxyService) { + for (JavaResourceImpl resource : componentType.getResources().values()) { + String name = resource.getName(); + + ObjectFactory objectFactory = + (ObjectFactory)componentContextProvider.getInstanceFactoryProvider().getFactories().get(resource.getElement()); + if (objectFactory == null) { + Class type = resource.getElement().getType(); + if (ComponentContext.class.equals(type)) { + objectFactory = new JavaComponentContextFactory(componentContextProvider); + } else if (RequestContext.class.equals(type)) { + objectFactory = new RequestContextObjectFactory(requestContextFactory, proxyService); + } else if (String.class.equals(type)) { + objectFactory = new JavaComponentNameFactory(componentContextProvider); + } else { + boolean optional = resource.isOptional(); + String mappedName = resource.getMappedName(); + objectFactory = createResourceObjectFactory(type, mappedName, optional, null); + } + } + componentContextProvider.addResourceFactory(name, objectFactory); + } + } + + private ResourceObjectFactory createResourceObjectFactory(Class type, + String mappedName, + boolean optional, + ResourceHost host) { + return new ResourceObjectFactory(type, mappedName, optional, host); + } + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + try { + return componentContextProvider.createInvoker(operation); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException(e); + } + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public Scope getScope() { + return new Scope(implementation.getJavaScope().getScope()); + } + + public void start() { + componentContextProvider.start(); + } + + public void stop() { + componentContextProvider.stop(); + } + + public InstanceWrapper createInstanceWrapper() { + return componentContextProvider.createInstanceWrapper(); + } + + public boolean isEagerInit() { + return implementation.isEagerInit(); + } + + public long getMaxAge() { + return implementation.getMaxAge(); + } + + public long getMaxIdleTime() { + return implementation.getMaxIdleTime(); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java new file mode 100644 index 0000000000..a444b56846 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev: 604245 $ $Date: 2007-12-14 10:07:40 -0800 (Fri, 14 Dec 2007) $ + */ +public class JavaImplementationProviderFactory implements ImplementationProviderFactory { + private JavaPropertyValueObjectFactory propertyValueObjectFactory; + private DataBindingExtensionPoint dataBindingRegistry; + private ProxyFactory proxyService; + private ComponentContextFactory componentContextFactory; + private RequestContextFactory requestContextFactory; + private Map> policyHandlerClassNames = null; + + public JavaImplementationProviderFactory(ProxyFactory proxyService, + DataBindingExtensionPoint dataBindingRegistry, + JavaPropertyValueObjectFactory propertyValueObjectFactory, + ComponentContextFactory componentContextFactory, + RequestContextFactory requestContextFactory, + Map> policyHandlerClassNames) { + super(); + this.proxyService = proxyService; + this.dataBindingRegistry = dataBindingRegistry; + this.propertyValueObjectFactory = propertyValueObjectFactory; + this.componentContextFactory = componentContextFactory; + this.requestContextFactory = requestContextFactory; + this.policyHandlerClassNames = policyHandlerClassNames; + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + JavaImplementation implementation) { + return new JavaImplementationProvider(component, + implementation, + proxyService, + dataBindingRegistry, + propertyValueObjectFactory, + componentContextFactory, + requestContextFactory, + policyHandlerClassNames); + } + + public Class getModelType() { + return JavaImplementation.class; + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java new file mode 100644 index 0000000000..f42a264c38 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.lang.annotation.ElementType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactory; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactoryProvider; +import org.apache.tuscany.sca.implementation.java.context.ReflectiveInstanceFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.FieldInjector; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.injection.InvalidAccessorException; +import org.apache.tuscany.sca.implementation.java.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.MethodInjector; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; + +/** + * Encapsulates configuration for a Java-based atomic component + * + * @version $Rev: 639649 $ $Date: 2008-03-21 06:04:01 -0800 (Fri, 21 Mar 2008) $ + */ +public class JavaInstanceFactoryProvider implements InstanceFactoryProvider { + private JavaImplementation definition; + private ProxyFactory proxyService; + + private final List injectionSites; + private final EventInvoker initInvoker; + private final EventInvoker destroyInvoker; + private final Map factories = new HashMap(); + + public JavaInstanceFactoryProvider(JavaImplementation definition) { + this.definition = definition; + this.initInvoker = definition.getInitMethod() == null ? null : new MethodEventInvoker(definition + .getInitMethod()); + this.destroyInvoker = definition.getDestroyMethod() == null ? null : new MethodEventInvoker(definition + .getDestroyMethod()); + injectionSites = new ArrayList(); + } + + ProxyFactory getProxyFactory() { + return proxyService; + } + + void setProxyFactory(ProxyFactory proxyService) { + this.proxyService = proxyService; + } + + /** + * @return the definition + */ + JavaImplementation getImplementation() { + return definition; + } + + @SuppressWarnings("unchecked") + public InstanceFactory createFactory() { + ObjectFactory[] initArgs = getConstructorArgs(); + Injector[] injectors = getInjectors(); + return new ReflectiveInstanceFactory((Constructor)definition.getConstructor().getConstructor(), + initArgs, injectors, initInvoker, destroyInvoker); + } + + private ObjectFactory[] getConstructorArgs() { + JavaConstructorImpl constructor = definition.getConstructor(); + ObjectFactory[] initArgs = new ObjectFactory[constructor.getParameters().length]; + for (int i = 0; i < initArgs.length; i++) { + ObjectFactory factory = (ObjectFactory)factories.get(constructor.getParameters()[i]); + assert factory != null; + initArgs[i] = factory; + } + return initArgs; + } + + @SuppressWarnings("unchecked") + private Injector[] getInjectors() { + // work around JDK1.5 issue with allocating generic arrays + @SuppressWarnings("unchecked") + Injector[] injectors = new Injector[injectionSites.size()]; + + int i = 0; + for (JavaElementImpl element : injectionSites) { + Object obj = factories.get(element); + if (obj != null) { + if (obj instanceof ObjectFactory) { + ObjectFactory factory = (ObjectFactory)obj; + Member member = (Member)element.getAnchor(); + if (element.getElementType() == ElementType.FIELD) { + injectors[i++] = new FieldInjector((Field)member, factory); + } else if (element.getElementType() == ElementType.PARAMETER && member instanceof Method) { + injectors[i++] = new MethodInjector((Method)member, factory); + } else if (member instanceof Constructor) { + // Ignore + } else { + throw new AssertionError(String.valueOf(element)); + } + } else { + injectors[i++] = createMultiplicityInjector(element, (List>)obj); + } + } + } + return injectors; + } + + private Injector createMultiplicityInjector(JavaElementImpl element, List> factories) { + Class interfaceType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + + if (element.getAnchor() instanceof Field) { + Field field = (Field)element.getAnchor(); + if (field.getType().isArray()) { + return new FieldInjector(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector(field, new ListMultiplicityObjectFactory(factories)); + } + } else if (element.getAnchor() instanceof Method) { + Method method = (Method)element.getAnchor(); + if (method.getParameterTypes()[0].isArray()) { + return new MethodInjector(method, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new MethodInjector(method, new ListMultiplicityObjectFactory(factories)); + } + } else { + throw new InvalidAccessorException("Member must be a field or method: " + element.getName()); + } + } + + @SuppressWarnings("unchecked") + public Class getImplementationClass() { + return (Class)definition.getJavaClass(); + } + + public void setObjectFactory(JavaElementImpl element, ObjectFactory objectFactory) { + factories.put(element, objectFactory); + } + + public void setObjectFactories(JavaElementImpl element, List> objectFactory) { + factories.put(element, objectFactory); + } + + /** + * @return the injectionSites + */ + List getInjectionSites() { + return injectionSites; + } + + /** + * @return the factories + */ + Map getFactories() { + return factories; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaPolicyHandlingRuntimeWireProcessor.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaPolicyHandlingRuntimeWireProcessor.java new file mode 100644 index 0000000000..1163c364c9 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaPolicyHandlingRuntimeWireProcessor.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.util.PolicyHandler; +import org.apache.tuscany.sca.policy.util.PolicyHandlerUtils; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; + +/** + * Processor to inject policy handling interceptor whenever PolicySets are specified in a Java Implementation + */ +public class JavaPolicyHandlingRuntimeWireProcessor implements RuntimeWireProcessor { + private final static Logger logger = Logger.getLogger(JavaPolicyHandlingRuntimeWireProcessor.class.getName()); + + public JavaPolicyHandlingRuntimeWireProcessor() { + super(); + } + + public void process(RuntimeWire wire) { + /*Contract contract = wire.getSource().getContract(); + if (!(contract instanceof RuntimeComponentReference)) { + return; + }*/ + + RuntimeComponent component = wire.getTarget().getComponent(); + if (component != null && component.getImplementation() instanceof JavaImplementation) { + JavaImplementation javaImpl = (JavaImplementation)component.getImplementation(); + if (javaImpl instanceof PolicySetAttachPoint) { + PolicyHandler policyHandler = null; + List implPolicyHandlers = new ArrayList(); + PolicySetAttachPoint policiedImpl = (PolicySetAttachPoint)javaImpl; + + try { + //for ( PolicySet policySet : policiedImpl.getPolicySets() ) { + for (PolicySet policySet : component.getPolicySets()) { + policyHandler = + PolicyHandlerUtils.findPolicyHandler(policySet, javaImpl.getPolicyHandlerClassNames()); + if (policyHandler != null) { + policyHandler.setUp(javaImpl); + implPolicyHandlers.add(policyHandler); + } else { + //FIXME: to be removed after the PolicyHandler story has crystalized.. + //maybe replace with exception then... + logger.warning("No PolicyHandler registered for PolicySet - " + policySet.getName()); + } + } + + List applicablePolicyHandlers = null; + for (InvocationChain chain : wire.getInvocationChains()) { + applicablePolicyHandlers = new ArrayList(); + if (javaImpl instanceof OperationsConfigurator) { + String operationName = chain.getTargetOperation().getName(); + OperationsConfigurator opConfigurator = (OperationsConfigurator)component; + for (ConfiguredOperation confOp : opConfigurator.getConfiguredOperations()) { + if (confOp.getName().equals(operationName)) { + for (PolicySet policySet : confOp.getPolicySets()) { + policyHandler = + PolicyHandlerUtils.findPolicyHandler(policySet, javaImpl + .getPolicyHandlerClassNames()); + if (policyHandler != null) { + policyHandler.setUp(javaImpl); + applicablePolicyHandlers.add(policyHandler); + } else { + logger.warning("No PolicyHandler registered for " + policySet); + } + } + break; + } + } + + //if no policies have been specified at the operation level then simply + //apply whatever is specified for the implementation level + if (applicablePolicyHandlers.isEmpty()) { + applicablePolicyHandlers = implPolicyHandlers; + } + } + + if (!applicablePolicyHandlers.isEmpty()) { + String phase = + (wire.getSource().getContract() instanceof ComponentReference) ? Phase.REFERENCE_POLICY + : Phase.SERVICE_POLICY; + + chain.addInterceptor(Phase.IMPLEMENTATION_POLICY, new PolicyHandlingInterceptor(chain.getTargetOperation(), + applicablePolicyHandlers)); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.java new file mode 100644 index 0000000000..e1a0c6d326 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + +/** + * Performs an wire on a method of a given instance + * + * @version $Rev: 639649 $ $Date: 2008-03-21 06:04:01 -0800 (Fri, 21 Mar 2008) $ + */ +public class MethodEventInvoker implements EventInvoker { + private final Method method; + + /** + * Instantiates an invoker for the given method + */ + public MethodEventInvoker(Method method) { + assert method != null; + this.method = method; + } + + public void invokeEvent(T instance) throws EventInvocationException { + try { + method.invoke(instance, (Object[]) null); + } catch (IllegalArgumentException e) { + String name = method.getName(); + throw new EventInvocationException("Exception thrown by event method [" + name + "]", e.getCause()); + } catch (IllegalAccessException e) { + String name = method.getName(); + throw new EventInvocationException("Method is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = method.getName(); + throw new EventInvocationException("Exception thrown by event method [" + name + "]", e.getCause()); + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java new file mode 100644 index 0000000000..a7b175cf9b --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + + +/** + * Raised when a component has conversational scope but no conversational contract + * + * @version $Rev: 487877 $ $Date: 2006-12-16 15:32:16 -0500 (Sat, 16 Dec 2006) $ + */ +public class NoConversationalContractException extends Exception { + + private static final long serialVersionUID = -1157790036638157539L; + + public NoConversationalContractException(String message) { + super(message); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PolicyHandlingInterceptor.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PolicyHandlingInterceptor.java new file mode 100644 index 0000000000..210068841b --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/PolicyHandlingInterceptor.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.util.List; + +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.policy.util.PolicyHandler; + +/** + * An interceptor to invoke policy handlers before and after the invocation of operations on + * an implementation. + */ +public class PolicyHandlingInterceptor implements Interceptor { + private Invoker next; + private List policyHandlers = null; + private Operation targetOperation = null; + + public PolicyHandlingInterceptor(Operation targetOperation, List policyHandlers) { + this.policyHandlers = policyHandlers; + this.targetOperation = targetOperation; + } + + public Message invoke(Message msg) { + try { + applyPreInvocationPolicies(targetOperation, msg); + msg = next.invoke(msg); + } finally { + applyPostInvocationPolices(targetOperation, msg); + } + return msg; + } + + public void setNext(Invoker next) { + this.next = next; + } + + public Invoker getNext() { + return next; + } + + private void applyPreInvocationPolicies(Object... context) { + for (PolicyHandler policyHandler : policyHandlers) { + policyHandler.beforeInvoke(context); + } + } + + private void applyPostInvocationPolices(Object... context) { + for ( int count = policyHandlers.size() - 1 ; count >= 0 ; --count) { + policyHandlers.get(count).afterInvoke(context); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.java b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.java new file mode 100644 index 0000000000..ff7e906121 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/module/JavaRuntimeModuleActivator.java @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.module; + +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.core.invocation.CglibProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultTransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.MediatorImpl; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.AllowsPassByReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ComponentNameProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConstructorProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ContextProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConversationIDProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ConversationProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.DestroyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.EagerInitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.InitProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PolicyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.PropertyProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ReferenceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ResourceProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ScopeProcessor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.ServiceProcessor; +import org.apache.tuscany.sca.implementation.java.invocation.JavaCallbackRuntimeWireProcessor; +import org.apache.tuscany.sca.implementation.java.invocation.JavaImplementationProviderFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.util.PolicyHandlerDefinitionsLoader; +import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; +import org.apache.tuscany.sca.provider.DefaultProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.DefaultWireProcessorExtensionPoint; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; + +/** + * @version $Rev: 641726 $ $Date: 2008-03-26 23:24:37 -0800 (Wed, 26 Mar 2008) $ + */ +public class JavaRuntimeModuleActivator implements ModuleActivator { + + public JavaRuntimeModuleActivator() { + } + + public void start(ExtensionPointRegistry registry) { + + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = factories.getFactory(AssemblyFactory.class); + PolicyFactory policyFactory = factories.getFactory(PolicyFactory.class); + + MessageFactory messageFactory = factories.getFactory(MessageFactory.class); + ProxyFactoryExtensionPoint proxyFactory = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + proxyFactory.setClassProxyFactory(new CglibProxyFactory(messageFactory, proxyFactory + .getInterfaceContractMapper())); + + JavaInterfaceFactory javaFactory = factories.getFactory(JavaInterfaceFactory.class); + JavaImplementationFactory javaImplementationFactory = factories.getFactory(JavaImplementationFactory.class); + + if (javaImplementationFactory == null) { + javaImplementationFactory = new DefaultJavaImplementationFactory(); + factories.addFactory(javaImplementationFactory); + + } + + BaseJavaClassVisitor[] extensions = + new BaseJavaClassVisitor[] {new ConstructorProcessor(assemblyFactory), + + // should not be loaded when running on Android platform, cause + // this class uses the Class.isAnnotationPresent method, which is + // not supported yet by the Android platform + new AllowsPassByReferenceProcessor(assemblyFactory), + + new ComponentNameProcessor(assemblyFactory), + new ContextProcessor(assemblyFactory), + new ConversationIDProcessor(assemblyFactory), + + // should not be loaded when running on Android platform, cause + // this class uses the Class.getAnnotation method, which is + // not supported yet by the Android platform + new ConversationProcessor(assemblyFactory), + + new DestroyProcessor(assemblyFactory), + + // should not be loaded when running on Android platform, cause + // this class uses the Class.getAnnotation method, which is + // not supported yet by the Android platform + new EagerInitProcessor(assemblyFactory), + + new InitProcessor(assemblyFactory), + new PropertyProcessor(assemblyFactory), + new ReferenceProcessor(assemblyFactory, javaFactory), + new ResourceProcessor(assemblyFactory), + + // should not be loaded when running on Android platform, cause + // this class uses the Class.getAnnotation method, which is + // not supported yet by the Android platform + new ScopeProcessor(assemblyFactory), + + // this class uses the org.osoa.sca.annotations.Service class, but + // Android seems not being able to convert this class to its internal class + // representation. The Android compiler is outputing the following message: + + /* [2008-04-25 19:36:22 - CalculatorAndroid] + trouble processing: + [2008-04-25 19:36:22 - CalculatorAndroid] truncated annotation attribute + ...while parsing AnnotationDefault attribute at offset 0000020b + ...while parsing attributes[1] + ...while parsing methods[0] + ...while parsing org/osoa/sca/annotations/Service.class + ...while processing org/osoa/sca/annotations/Service.class + [2008-04-25 19:36:26 - CalculatorAndroid] 1 warning*/ + + // So, the class will not be loaded + new ServiceProcessor(assemblyFactory, javaFactory), + + // should not be loaded when running on Android platform, cause + // this class uses the Class.getAnnotation method, which is + // not supported yet by the Android platform + new HeuristicPojoProcessor(assemblyFactory, javaFactory), + + // should not be loaded when running on Android platform, cause + // this class uses the Class.getAnnotation method, which is + // not supported yet by the Android platform + new PolicyProcessor(assemblyFactory, policyFactory) + }; + + for (JavaClassVisitor extension : extensions) { + javaImplementationFactory.addClassVisitor(extension); + } + + registry.addExtensionPoint(new DefaultDataBindingExtensionPoint()); + registry.addExtensionPoint(new DefaultTransformerExtensionPoint()); + DataBindingExtensionPoint dataBindings = registry.getExtensionPoint(DataBindingExtensionPoint.class); + TransformerExtensionPoint transformers = registry.getExtensionPoint(TransformerExtensionPoint.class); + MediatorImpl mediator = new MediatorImpl(dataBindings, transformers); + JavaPropertyValueObjectFactory factory = new JavaPropertyValueObjectFactory(mediator); + + ContextFactoryExtensionPoint contextFactories = registry.getExtensionPoint(ContextFactoryExtensionPoint.class); + ComponentContextFactory componentContextFactory = contextFactories.getFactory(ComponentContextFactory.class); + RequestContextFactory requestContextFactory = contextFactories.getFactory(RequestContextFactory.class); + + Map> policyHandlerClassNames = null; + policyHandlerClassNames = PolicyHandlerDefinitionsLoader.loadPolicyHandlerClassnames(); + + JavaImplementationProviderFactory javaImplementationProviderFactory = + new JavaImplementationProviderFactory(proxyFactory, dataBindings, factory, componentContextFactory, + requestContextFactory, policyHandlerClassNames); + + ProviderFactoryExtensionPoint providerFactories = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + if (providerFactories == null) { + providerFactories = new DefaultProviderFactoryExtensionPoint(registry); + registry.addExtensionPoint(providerFactories); + + } + + providerFactories.addProviderFactory(javaImplementationProviderFactory); + + InterfaceContractMapper interfaceContractMapper = registry.getExtensionPoint(InterfaceContractMapper.class); + RuntimeWireProcessorExtensionPoint wireProcessorExtensionPoint = + registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class); + + if (wireProcessorExtensionPoint == null) { + wireProcessorExtensionPoint = new DefaultWireProcessorExtensionPoint(); + registry.addExtensionPoint(wireProcessorExtensionPoint); + + } + + if (wireProcessorExtensionPoint != null) { + wireProcessorExtensionPoint.addWireProcessor(new JavaCallbackRuntimeWireProcessor(interfaceContractMapper, + javaFactory)); + //wireProcessorExtensionPoint.addWireProcessor(new JavaPolicyHandlingRuntimeWireProcessor()); + } + } + + public void stop(ExtensionPointRegistry registry) { + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator b/branches/sca-android/tuscany-implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator new file mode 100644 index 0000000000..0871ddf4be --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator @@ -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. +# Implementation class for the ModuleActivator +org.apache.tuscany.sca.implementation.java.module.JavaRuntimeModuleActivator diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.java new file mode 100644 index 0000000000..0323c15b09 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import junit.framework.TestCase; + + +/** + * Tests wires that are configured with a multiplicity + * + * @version $Rev: 537424 $ $Date: 2007-05-12 06:47:18 -0700 (Sat, 12 May 2007) $ + */ +public class MultiplicityTestCase extends TestCase { + + public void testMultiplicity() throws Exception { + // TODO implement + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java new file mode 100644 index 0000000000..c9b1987f25 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import static org.easymock.EasyMock.createMock; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; +import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; +import org.easymock.EasyMock; + +/** + * @version $Rev: 568826 $ $Date: 2007-08-22 22:27:34 -0700 (Wed, 22 Aug 2007) $ + */ +public class ReflectiveInstanceWrapperTestCase extends TestCase { + private ReflectiveInstanceWrapper wrapper; + private Object instance; + private EventInvoker initInvoker; + private EventInvoker destroyInvoker; + + public void testWithNoCallbacks() { + wrapper = new ReflectiveInstanceWrapper(instance, null, null); + try { + wrapper.start(); + } catch (TargetInitializationException e) { + fail(); + } + try { + wrapper.stop(); + } catch (TargetDestructionException e) { + fail(); + } + } + + public void testWithStartCallback() { + initInvoker.invokeEvent(instance); + EasyMock.replay(initInvoker); + wrapper = new ReflectiveInstanceWrapper(instance, initInvoker, null); + try { + wrapper.start(); + } catch (TargetInitializationException e) { + fail(); + } + EasyMock.verify(initInvoker); + } + + public void testWithStopCallback() { + destroyInvoker.invokeEvent(instance); + EasyMock.replay(destroyInvoker); + wrapper = new ReflectiveInstanceWrapper(instance, null, destroyInvoker); + try { + wrapper.stop(); + } catch (TargetDestructionException e) { + fail(); + } + EasyMock.verify(destroyInvoker); + } + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + instance = new Object(); + initInvoker = createMock(EventInvoker.class); + destroyInvoker = createMock(EventInvoker.class); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java new file mode 100644 index 0000000000..ef338297ef --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import static org.easymock.EasyMock.createMock; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.easymock.EasyMock; + +/** + * @version $Rev: 538423 $ $Date: 2007-05-15 21:11:06 -0700 (Tue, 15 May 2007) $ + */ +public class CallbackWireObjectFactoryTestCase extends TestCase { + + @SuppressWarnings({"unchecked"}) + public void testCreateInstance() throws Exception { + ProxyFactory service = createMock(ProxyFactory.class); + Foo foo = new Foo() { + }; + EasyMock.expect(service.createCallbackProxy(EasyMock.eq(Foo.class), EasyMock.isA(List.class))).andReturn(foo); + EasyMock.replay(service); + List wires = new ArrayList(); + CallbackWireObjectFactory factory = new CallbackWireObjectFactory(Foo.class, service, wires); + assertEquals(foo, factory.getInstance()); + EasyMock.verify(service); + } + + private interface Foo { + + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.java new file mode 100644 index 0000000000..1f34fc5e12 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Field; + +import junit.framework.TestCase; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class FieldInjectorTestCase extends TestCase { + + protected Field protectedField; + + public void testIllegalAccess() throws Exception { + FieldInjector injector = new FieldInjector(protectedField, new SingletonObjectFactory("foo")); + Foo foo = new Foo(); + injector.inject(foo); + assertEquals("foo", foo.hidden); + } + + + @Override + protected void setUp() throws Exception { + super.setUp(); + protectedField = Foo.class.getDeclaredField("hidden"); + } + + private class Foo { + private String hidden; + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java new file mode 100644 index 0000000000..4b7f78aabf --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.implementation.java.invocation.EventInvocationException; +import org.apache.tuscany.sca.implementation.java.invocation.MethodEventInvoker; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class MethodEventInvokerTestCase extends TestCase { + private Method privateMethod; + private Method exceptionMethod; + + public void testIllegalAccess() throws Exception { + MethodEventInvoker injector = new MethodEventInvoker(privateMethod); + try { + injector.invokeEvent(new Foo()); + fail(); + } catch (EventInvocationException e) { + // expected + } + } + + public void testException() throws Exception { + MethodEventInvoker injector = new MethodEventInvoker(exceptionMethod); + try { + injector.invokeEvent(new Foo()); + fail(); + } catch (RuntimeException e) { + // expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + privateMethod = MethodEventInvokerTestCase.Foo.class.getDeclaredMethod("hidden"); + exceptionMethod = MethodEventInvokerTestCase.Foo.class.getDeclaredMethod("exception"); + + } + + public class Foo { + + public void foo() { + } + + private void hidden() { + } + + public void exception() { + throw new RuntimeException(); + } + + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.java new file mode 100644 index 0000000000..ca2755f811 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.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.implementation.java.injection; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class MethodInjectorTestCase extends TestCase { + private Method fooMethod; + private Method privateMethod; + private Method exceptionMethod; + + public void testIllegalArgument() throws Exception { + ObjectFactory factory = new SingletonObjectFactory(new Object()); + MethodInjector injector = new MethodInjector(fooMethod, factory); + try { + injector.inject(new Foo()); + fail(); + } catch (ObjectCreationException e) { + // expected + } + } + + public void testException() throws Exception { + ObjectFactory factory = new SingletonObjectFactory("foo"); + MethodInjector injector = new MethodInjector(exceptionMethod, factory); + try { + injector.inject(new Foo()); + fail(); + } catch (RuntimeException e) { + // expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + fooMethod = Foo.class.getMethod("foo", String.class); + privateMethod = Foo.class.getDeclaredMethod("hidden", String.class); + exceptionMethod = Foo.class.getDeclaredMethod("exception", String.class); + + } + + private class Foo { + + public void foo(String bar) { + } + + private void hidden(String bar) { + } + + public void exception(String bar) { + throw new RuntimeException(); + } + + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactoryTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactoryTestCase.java new file mode 100644 index 0000000000..3b25724694 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactoryTestCase.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import junit.framework.TestCase; + +/** + * @version $Rev: 557408 $ $Date: 2007-07-18 14:58:03 -0700 (Wed, 18 Jul 2007) $ + */ +public class RequestContextObjectFactoryTestCase extends TestCase { + + public void testInstanceCreate() { + RequestContextObjectFactory factory = new RequestContextObjectFactory(null); + assertNotNull(factory.getInstance()); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java new file mode 100644 index 0000000000..76947c2488 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +/** + * @version $Rev: 537744 $ $Date: 2007-05-14 01:00:18 -0700 (Mon, 14 May 2007) $ + */ +public class ResourceObjectFactoryTestCase extends TestCase { + + public void testResolveFromHostByType() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn("foo"); + EasyMock.replay(host); + ResourceObjectFactory factory = new ResourceObjectFactory(String.class, false, host); + assertEquals("foo", factory.getInstance()); + EasyMock.verify(host); + } + + public void testResolveFromHostByName() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class), + EasyMock.eq("sca://localhost/bar"))).andReturn("foo"); + EasyMock.replay(host); + ResourceObjectFactory factory = + new ResourceObjectFactory(String.class, "sca://localhost/bar", false, host); + assertEquals("foo", factory.getInstance()); + EasyMock.verify(host); + } + + + public void testResolveFromParentThenResolveFromHostNotFound() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn(null); + EasyMock.replay(host); + ResourceObjectFactory factory = new ResourceObjectFactory(String.class, true, host); + assertNull(factory.getInstance()); + EasyMock.verify(host); + } + + public void testResolveByTypeNotFound() throws Exception { +// ResourceHost host = EasyMock.createMock(ResourceHost.class); +// EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn(null); +// EasyMock.replay(host); +// +// RuntimeWire wire = EasyMock.createMock(RuntimeWire.class); +// EasyMock.expect(wire.getTargetInstance()).andReturn(null); +// EasyMock.replay(wire); +// +// ResourceObjectFactory factory = new ResourceObjectFactory(String.class, false, host); +// try { +// factory.getInstance(); +// fail(); +// } catch (ResourceNotFoundException e) { +// //expected +// } +// EasyMock.verify(host); + } + + public void testResolveByTypeNotFoundOptional() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn(null); + EasyMock.replay(host); + ResourceObjectFactory factory = new ResourceObjectFactory(String.class, true, host); + assertNull(factory.getInstance()); + EasyMock.verify(host); + } + + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java new file mode 100644 index 0000000000..2132e3c3e1 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Implementation of ObjectFactory that returns a single instance, typically an immutable type. + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class SingletonObjectFactory implements ObjectFactory { + private final T instance; + + public SingletonObjectFactory(T instance) { + this.instance = instance; + } + + public T getInstance() { + return instance; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.java new file mode 100644 index 0000000000..59c810e7f0 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import junit.framework.TestCase; + +/** + * @version $Rev: 537744 $ $Date: 2007-05-14 01:00:18 -0700 (Mon, 14 May 2007) $ + */ +public class SingletonObjectFactoryTestCase extends TestCase { + + public void testSingleton() throws Exception { + Object o = new Object(); + SingletonObjectFactory factory = new SingletonObjectFactory(o); + assertEquals(o, factory.getInstance()); + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java new file mode 100644 index 0000000000..08b7bfacbe --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Creates new instances of a Java class + * + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + * @see org.apache.tuscany.sca.implementation.java.injection.Injector + */ +public class TestObjectFactory implements ObjectFactory { + + private final Constructor ctr; + private ObjectFactory[] initializerFactories; + + /** + * Creates the object factory + * + * @param ctr the constructor to use when instantiating a new object + */ + public TestObjectFactory(Constructor ctr) { + assert ctr != null; + this.ctr = ctr; + initializerFactories = new ObjectFactory[ctr.getParameterTypes().length]; + } + + /** + * Creates the object factory + * + * @param ctr the constructor to use when instantiating a new object + * @param factories an ordered list of ObjectFactorys to use for returning constructor parameters + */ + public TestObjectFactory(Constructor ctr, List factories) { + assert ctr != null; + int params = ctr.getParameterTypes().length; + assert params == factories.size(); + this.ctr = ctr; + initializerFactories = new ObjectFactory[params]; + int i = 0; + for (ObjectFactory factory : factories) { + initializerFactories[i] = factory; + i++; + } + } + + /** + * Returns the ordered array of ObjectFactorys use in creating constructor parameters + */ + public ObjectFactory[] getInitializerFactories() { + return initializerFactories; + } + + /** + * Sets an ObjectFactorys to use in creating constructor parameter + * + * @param pos the constructor parameter position + * @param factory the object factory + */ + public void setInitializerFactory(int pos, ObjectFactory factory) { + assert pos < initializerFactories.length; + initializerFactories[pos] = factory; + } + + /** + * Creates a new instance of an object + */ + public T getInstance() throws ObjectCreationException { + int size = initializerFactories.length; + Object[] initargs = new Object[size]; + // create the constructor arg array + for (int i = 0; i < size; i++) { + ObjectFactory objectFactory = initializerFactories[i]; + if (objectFactory == null) { + // this can happen if a reference is optional + initargs[i] = null; + } else { + initargs[i] = objectFactory.getInstance(); + } + } + try { + ctr.setAccessible(true); + return ctr.newInstance(initargs); + } catch (IllegalArgumentException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java new file mode 100644 index 0000000000..12591b2382 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * @version $Rev: 567619 $ $Date: 2007-08-20 02:29:57 -0700 (Mon, 20 Aug 2007) $ + */ +public class TestObjectFactoryTestCase extends TestCase { + + private Constructor ctor; + + public void testConstructorInjection() throws Exception { + List initializers = new ArrayList(); + initializers.add(new SingletonObjectFactory("foo")); + TestObjectFactory factory = new TestObjectFactory(ctor, initializers); + Foo foo = factory.getInstance(); + assertEquals("foo", foo.foo); + } + + /** + * Verifies null parameters can be passed to a constructor. This is valid when a reference is optional during + * constructor injection + */ + public void testConstructorInjectionOptionalParam() throws Exception { + List initializers = new ArrayList(); + initializers.add(null); + TestObjectFactory factory = new TestObjectFactory(ctor, initializers); + Foo foo = factory.getInstance(); + assertNull(foo.foo); + } + + public void testConstructorInitializerInjection() throws Exception { + TestObjectFactory factory = new TestObjectFactory(ctor); + factory.setInitializerFactory(0, new SingletonObjectFactory("foo")); + Foo foo = factory.getInstance(); + assertEquals("foo", foo.foo); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + ctor = Foo.class.getConstructor(String.class); + } + + private static class Foo { + + private String foo; + + public Foo(String foo) { + this.foo = foo; + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.java new file mode 100644 index 0000000000..0ace1336df --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.util; + + +public class Bean1 extends SuperBean { + + public static final int ALL_BEAN1_FIELDS = 6 + ALL_SUPER_FIELDS; + public static final int ALL_BEAN1_PUBLIC_PROTECTED_FIELDS = 5 + ALL_SUPER_PUBLIC_PROTECTED_FIELDS; + public static final int ALL_BEAN1_METHODS = 4 + ALL_SUPER_METHODS - 1; + public String field3; + protected String field2; + private String field1; + + public void setMethod1(String param) { + } + + public void setMethod1(int param) { + } + + @Override + public void override(String param) throws Exception { + } + + + public void noOverride(String param) throws Exception { + } + + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.java new file mode 100644 index 0000000000..46ab21eca7 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.util; + +import java.util.List; + +import junit.framework.AssertionFailedError; + +public class Bean2 { + + private List methodList; + private List fieldList; + + public List getMethodList() { + return methodList; + } + + public void setMethodList(List list) { + methodList = list; + } + + public List getfieldList() { + return fieldList; + } + + public void setfieldList(List list) { + throw new AssertionFailedError("setter inadvertantly called"); + } + + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.java new file mode 100644 index 0000000000..a6d2787a45 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.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.implementation.java.util; + +/** + * Implementations are used in wiring tests + * + * @version $Rev: 567313 $ $Date: 2007-08-18 11:38:44 -0700 (Sat, 18 Aug 2007) $ + */ +public interface Entry { + + String getString(); + + void setString(String val); +} + diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java new file mode 100644 index 0000000000..7b3b5f0a36 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; + +public class JavaIntrospectionHelperTestCase extends TestCase { + + private List testNoGenericsList; + private List testList; + private Map testMap; + private Entry[] testArray; + private String[] testStringArray; + + public JavaIntrospectionHelperTestCase() { + super(); + } + + public JavaIntrospectionHelperTestCase(String arg0) { + super(arg0); + } + + public void testBean1AllPublicProtectedFields() throws Exception { + Set beanFields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(Bean1.class, true); + assertEquals(4, beanFields.size()); //Bean1.ALL_BEAN1_PUBLIC_PROTECTED_FIELDS + } + + public void testGetSuperAllMethods() throws Exception { + Set superBeanMethods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(SuperBean.class, true); + assertEquals(SuperBean.ALL_SUPER_METHODS, superBeanMethods.size()); + } + + public void testGetBean1AllMethods() throws Exception { + Set beanMethods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class, true); + assertEquals(Bean1.ALL_BEAN1_METHODS, beanMethods.size()); + } + + public void testOverrideMethod() throws Exception { + Set beanFields = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class, true); + boolean invoked = false; + for (Method method : beanFields) { + if (method.getName().equals("override")) { + method.invoke(new Bean1(), "foo"); + invoked = true; + } + } + if (!invoked) { + throw new Exception("Override never invoked"); + } + } + + public void testNoOverrideMethod() throws Exception { + Set beanFields = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class, true); + boolean found = false; + for (Method method : beanFields) { + if (method.getName().equals("noOverride") && method.getParameterTypes().length == 0) { + found = true; + } + } + if (!found) { + throw new Exception("No override not found"); + } + } + + public void testDefaultConstructor() throws Exception { + Constructor ctr = JavaIntrospectionHelper.getDefaultConstructor(Bean2.class); + assertEquals(ctr, Bean2.class.getConstructor()); + assertTrue(Bean2.class == ctr.newInstance((Object[]) null).getClass()); + } + + + public void testGetAllInterfaces() { + Set interfaces = JavaIntrospectionHelper.getAllInterfaces(Z.class); + assertEquals(2, interfaces.size()); + assertTrue(interfaces.contains(W.class)); + assertTrue(interfaces.contains(W2.class)); + } + + + public void testGetAllInterfacesObject() { + Set interfaces = JavaIntrospectionHelper.getAllInterfaces(Object.class); + assertEquals(0, interfaces.size()); + } + + public void testGetAllInterfacesNoInterfaces() { + Set interfaces = JavaIntrospectionHelper.getAllInterfaces(NoInterface.class); + assertEquals(0, interfaces.size()); + } + + /** + * Tests generics introspection capabilities + */ + public void testGenerics() throws Exception { + + List classes = JavaIntrospectionHelper.getGenerics(getClass().getDeclaredField("testList").getGenericType()); + assertEquals(1, classes.size()); + assertEquals(String.class, classes.get(0)); + + classes = + JavaIntrospectionHelper.getGenerics(getClass().getDeclaredField("testNoGenericsList").getGenericType()); + assertEquals(0, classes.size()); + + classes = JavaIntrospectionHelper.getGenerics(getClass().getDeclaredField("testMap").getGenericType()); + assertEquals(2, classes.size()); + assertEquals(String.class, classes.get(0)); + assertEquals(Bean1.class, classes.get(1)); + + classes = JavaIntrospectionHelper + .getGenerics(getClass().getDeclaredMethod("fooMethod", Map.class).getGenericParameterTypes()[0]); + assertEquals(2, classes.size()); + assertEquals(String.class, classes.get(0)); + assertEquals(Bean1.class, classes.get(1)); + + classes = JavaIntrospectionHelper + .getGenerics(getClass().getDeclaredMethod("fooMethod", List.class).getGenericParameterTypes()[0]); + assertEquals(1, classes.size()); + assertEquals(String.class, classes.get(0)); + + } + + private void fooMethod(List foo) { + + } + + private void fooMethod(Map foo) { + + } + + public void setTestArray(Entry[] array) { + } + + private interface W { + + } + + private interface W2 { + + } + + private class X implements W { + + } + + private class Y extends X implements W, W2 { + + } + + private class Z extends Y { + + } + + private class NoInterface { + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.java b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.java new file mode 100644 index 0000000000..4923233ea9 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.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.implementation.java.util; + +/** + * @version $Rev: 537424 $ $Date: 2007-05-12 06:47:18 -0700 (Sat, 12 May 2007) $ + */ +public class SuperBean { + + public static final int ALL_SUPER_FIELDS = 6; + public static final int ALL_SUPER_PUBLIC_PROTECTED_FIELDS = 5; + public static final int ALL_SUPER_METHODS = 4; + public String superField2; + + protected String superField3; + + private String superField1; + + public void setSuperMethod1(String param) { + } + + public void setSuperMethod1(int param) { + } + + public void override(String param) throws Exception { + throw new Exception("Override not handled"); + } + + public void noOverride() throws Exception { + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/.classpath b/branches/sca-android/tuscany-implementation-java-xml/.classpath new file mode 100644 index 0000000000..439458770c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/.classpath @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java-xml/.project b/branches/sca-android/tuscany-implementation-java-xml/.project new file mode 100644 index 0000000000..c9dbd24603 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/.project @@ -0,0 +1,39 @@ + + tuscany-implementation-java-xml + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly-xml + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-contribution + tuscany-contribution-namespace + tuscany-core-spi + tuscany-sca-api + tuscany-contribution-java + tuscany-binding-sca + tuscany-core + tuscany-interface-java + tuscany-contribution-impl + tuscany-contribution-xml + tuscany-contribution-resource + tuscany-node + tuscany-domain + tuscany-domain-api + tuscany-node-api + tuscany-definitions-xml + tuscany-policy-xml + tuscany-implementation-java + tuscany-interface-java-xml + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java-xml/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-implementation-java-xml/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..c373d32c5c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:21:23 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-implementation-java-xml/DISCLAIMER b/branches/sca-android/tuscany-implementation-java-xml/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-implementation-java-xml/LICENSE b/branches/sca-android/tuscany-implementation-java-xml/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/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/branches/sca-android/tuscany-implementation-java-xml/NOTICE b/branches/sca-android/tuscany-implementation-java-xml/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-implementation-java-xml/pom.xml b/branches/sca-android/tuscany-implementation-java-xml/pom.xml new file mode 100644 index 0000000000..549570e238 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/pom.xml @@ -0,0 +1,79 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-implementation-java-xml + Apache Tuscany SCA Java Implementation XML Model + + + + + org.apache.tuscany.sca + tuscany-assembly-xml + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface-java-xml + ${version} + + + + org.apache.tuscany.sca + tuscany-contribution-impl + ${version} + test + + + + org.apache.tuscany.sca + tuscany-definitions + ${version} + test + + + + org.apache.tuscany.sca + tuscany-definitions-xml + ${version} + test + + + + org.apache.tuscany.sca + tuscany-implementation-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-binding-sca + 2.0-incubating-SNAPSHOT + test + + + diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java b/branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java new file mode 100644 index 0000000000..85cf3d7d0a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationConstants.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.xml; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.xml.Constants; + +public interface JavaImplementationConstants { + + String IMPLEMENTATION_JAVA = "implementation.java"; + QName IMPLEMENTATION_JAVA_QNAME = new QName(Constants.SCA10_NS, "implementation.java"); + String CLASS = "class"; + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java b/branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java new file mode 100644 index 0000000000..d66266fc0d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/main/java/org/apache/tuscany/sca/implementation/java/xml/JavaImplementationProcessor.java @@ -0,0 +1,280 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +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.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.xml.ConfiguredOperationProcessor; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.assembly.xml.PolicyAttachPointProcessor; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +public class JavaImplementationProcessor implements StAXArtifactProcessor, + JavaImplementationConstants { + + private JavaImplementationFactory javaFactory; + private AssemblyFactory assemblyFactory; + private PolicyFactory policyFactory; + private PolicyAttachPointProcessor policyProcessor; + private IntentAttachPointTypeFactory intentAttachPointTypeFactory; + private ConfiguredOperationProcessor configuredOperationProcessor; + + public JavaImplementationProcessor(ModelFactoryExtensionPoint modelFactories) { + modelFactories.addFactory(new DefaultAssemblyFactory()); + modelFactories.addFactory(new DefaultPolicyFactory()); + modelFactories.addFactory(new DefaultIntentAttachPointTypeFactory()); + + this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + this.policyFactory = modelFactories.getFactory(PolicyFactory.class); + this.javaFactory = modelFactories.getFactory(JavaImplementationFactory.class); + this.policyProcessor = new PolicyAttachPointProcessor(policyFactory); + this.intentAttachPointTypeFactory = modelFactories.getFactory(IntentAttachPointTypeFactory.class); + this.configuredOperationProcessor = new ConfiguredOperationProcessor(modelFactories); + + } + + public JavaImplementation read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + + // Read an + JavaImplementation javaImplementation = javaFactory.createJavaImplementation(); + + /*if ( javaImplementation instanceof PolicySetAttachPoint ) { + IntentAttachPointType implType = intentAttachPointTypeFactory.createImplementationType(); + implType.setName(getArtifactType()); + implType.setUnresolved(true); + ((PolicySetAttachPoint)javaImplementation).setType(implType); + }*/ + + javaImplementation.setUnresolved(true); + javaImplementation.setName(reader.getAttributeValue(null, CLASS)); + + // Read policies + policyProcessor.readPolicies(javaImplementation, reader); + + // read operation elements if exists or skip unto end element + int event; + ConfiguredOperation confOp = null; + while (reader.hasNext()) { + event = reader.next(); + switch ( event ) { + case START_ELEMENT : { + if ( Constants.OPERATION_QNAME.equals(reader.getName()) ) { + confOp = configuredOperationProcessor.read(reader); + if ( confOp != null ) { + ((OperationsConfigurator)javaImplementation).getConfiguredOperations().add(confOp); + } + } + } + break; + } + + if (event == END_ELEMENT && IMPLEMENTATION_JAVA_QNAME.equals(reader.getName())) { + break; + } + } + return javaImplementation; + } + + public void write(JavaImplementation javaImplementation, XMLStreamWriter writer) throws ContributionWriteException, + XMLStreamException { + + // Write an + policyProcessor.writePolicyPrefixes(javaImplementation, writer); + writer.writeStartElement(Constants.SCA10_NS, IMPLEMENTATION_JAVA); + policyProcessor.writePolicyAttributes(javaImplementation, writer); + + if (javaImplementation.getName() != null) { + writer.writeAttribute(CLASS, javaImplementation.getName()); + } + + writer.writeEndElement(); + } + + public void resolve(JavaImplementation javaImplementation, ModelResolver resolver) + throws ContributionResolveException { + + ClassReference classReference = new ClassReference(javaImplementation.getName()); + classReference = resolver.resolveModel(ClassReference.class, classReference); + Class javaClass = classReference.getJavaClass(); + if (javaClass == null) { + throw new ContributionResolveException(new ClassNotFoundException(javaImplementation.getName())); + } + javaImplementation.setJavaClass(javaClass); + javaImplementation.setUnresolved(false); + + try { + javaFactory.createJavaImplementation(javaImplementation, javaImplementation.getJavaClass()); + } catch (IntrospectionException e) { + throw new ContributionResolveException(e); + } + + mergeComponentType(resolver, javaImplementation); + + // FIXME the introspector should always create at least one service + if (javaImplementation.getServices().isEmpty()) { + javaImplementation.getServices().add(assemblyFactory.createService()); + } + } + + private JavaElementImpl getMemeber(JavaImplementation impl, String name, Class type) { + String setter = JavaIntrospectionHelper.toSetter(name); + try { + Method method = impl.getJavaClass().getDeclaredMethod(setter, type); + int mod = method.getModifiers(); + if ((Modifier.isPublic(mod) || Modifier.isProtected(mod)) && (!Modifier.isStatic(mod))) { + return new JavaElementImpl(method, 0); + } + } catch (NoSuchMethodException e) { + Field field; + try { + field = impl.getJavaClass().getDeclaredField(name); + int mod = field.getModifiers(); + if ((Modifier.isPublic(mod) || Modifier.isProtected(mod)) && (!Modifier.isStatic(mod))) { + return new JavaElementImpl(field); + } + } catch (NoSuchFieldException e1) { + // Ignore + } + } + return null; + } + + /** + * Merge the componentType from introspection and external file + * @param resolver + * @param impl + */ + private void mergeComponentType(ModelResolver resolver, JavaImplementation impl) { + // FIXME: Need to clarify how to merge + ComponentType componentType = getComponentType(resolver, impl); + if (componentType != null && !componentType.isUnresolved()) { + Map refMap = new HashMap(); + for (Reference ref : impl.getReferences()) { + refMap.put(ref.getName(), ref); + } + for (Reference reference : componentType.getReferences()) { + refMap.put(reference.getName(), reference); + } + impl.getReferences().clear(); + impl.getReferences().addAll(refMap.values()); + + // Try to match references by type + Map refMembers = impl.getReferenceMembers(); + for (Reference ref : impl.getReferences()) { + if (ref.getInterfaceContract() != null) { + Interface i = ref.getInterfaceContract().getInterface(); + if (i instanceof JavaInterface) { + Class type = ((JavaInterface)i).getJavaClass(); + if (!refMembers.containsKey(ref.getName())) { + JavaElementImpl e = getMemeber(impl, ref.getName(), type); + if (e != null) { + refMembers.put(ref.getName(), e); + } + } + } + } + } + + Map serviceMap = new HashMap(); + for (Service svc : impl.getServices()) { + serviceMap.put(svc.getName(), svc); + } + for (Service service : componentType.getServices()) { + serviceMap.put(service.getName(), service); + } + impl.getServices().clear(); + impl.getServices().addAll(serviceMap.values()); + + Map propMap = new HashMap(); + for (Property prop : impl.getProperties()) { + propMap.put(prop.getName(), prop); + } + for (Property property : componentType.getProperties()) { + propMap.put(property.getName(), property); + } + impl.getProperties().clear(); + impl.getProperties().addAll(propMap.values()); + + if (componentType.getConstrainingType() != null) { + impl.setConstrainingType(componentType.getConstrainingType()); + } + } + } + + private ComponentType getComponentType(ModelResolver resolver, JavaImplementation impl) { + String className = impl.getJavaClass().getName(); + String componentTypeURI = className.replace('.', '/') + ".componentType"; + ComponentType componentType = assemblyFactory.createComponentType(); + componentType.setUnresolved(true); + componentType.setURI(componentTypeURI); + componentType = resolver.resolveModel(ComponentType.class, componentType); + if (!componentType.isUnresolved()) { + return componentType; + } + return null; + } + + public QName getArtifactType() { + return IMPLEMENTATION_JAVA_QNAME; + } + + public Class getModelType() { + return JavaImplementation.class; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-android/tuscany-implementation-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..ff43eebcfc --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -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. + +# Implementation class for the artifact processor extension +org.apache.tuscany.sca.implementation.java.xml.JavaImplementationProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#implementation.java,model=org.apache.tuscany.sca.implementation.java.JavaImplementation diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddService.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddService.java new file mode 100644 index 0000000000..6392676e76 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddService.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +public interface AddService { + + double add(double n1, double n2); + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddServiceImpl.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddServiceImpl.java new file mode 100644 index 0000000000..2e7d6a5ed1 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/AddServiceImpl.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 calculator; + +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Scope; + +/** + * An implementation of the Add service + */ +@Scope("COMPOSITE") +@EagerInit +public class AddServiceImpl implements AddService { + + public double add(double n1, double n2) { + return n1 + n2; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorService.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorService.java new file mode 100644 index 0000000000..f5df6a42e8 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorService.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +/** + * The Calculator service interface. + */ +public interface CalculatorService { + + double add(double n1, double n2); + + double subtract(double n1, double n2); + + double multiply(double n1, double n2); + + double divide(double n1, double n2); + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.java new file mode 100644 index 0000000000..58d31bf217 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/CalculatorServiceImpl.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 calculator; + +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Scope; + +/** + * An implementation of the Calculator service. + */ +@Scope("COMPOSITE") +public class CalculatorServiceImpl implements CalculatorService { + + private AddService addService; + private SubtractService subtractService; + private MultiplyService multiplyService; + private DivideService divideService; + + @Reference + public void setAddService(AddService addService) { + this.addService = addService; + } + + @Reference + public void setSubtractService(SubtractService subtractService) { + this.subtractService = subtractService; + } + + @Reference + public void setDivideService(DivideService divideService) { + this.divideService = divideService; + } + + @Reference + public void setMultiplyService(MultiplyService multiplyService) { + this.multiplyService = multiplyService; + } + + public double add(double n1, double n2) { + return addService.add(n1, n2); + } + + public double subtract(double n1, double n2) { + return subtractService.subtract(n1, n2); + } + + public double multiply(double n1, double n2) { + return multiplyService.multiply(n1, n2); + } + + public double divide(double n1, double n2) { + return divideService.divide(n1, n2); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideService.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideService.java new file mode 100644 index 0000000000..3158458b5e --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideService.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +public interface DivideService { + + double divide(double n1, double n2); + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java new file mode 100644 index 0000000000..959312b464 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/DivideServiceImpl.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +import org.osoa.sca.annotations.Scope; + +/** + * An implementation of the Divide service. + */ +@Scope("COMPOSITE") +public class DivideServiceImpl implements DivideService { + + public double divide(double n1, double n2) { + return n1 / n2; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyService.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyService.java new file mode 100644 index 0000000000..62db05175e --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyService.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +public interface MultiplyService { + + double multiply(double n1, double n2); + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java new file mode 100644 index 0000000000..970d0c4d83 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/MultiplyServiceImpl.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +import org.osoa.sca.annotations.Scope; + +/** + * An implementation of the Multiply service. + */ +@Scope("COMPOSITE") +public class MultiplyServiceImpl implements MultiplyService { + + public double multiply(double n1, double n2) { + return n1 * n2; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractService.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractService.java new file mode 100644 index 0000000000..309f88f098 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractService.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +public interface SubtractService { + + double subtract(double n1, double n2); + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java new file mode 100644 index 0000000000..c1d867c687 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/calculator/SubtractServiceImpl.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package calculator; + +import org.osoa.sca.annotations.Scope; + +/** + * An implementation of the subtract service. + */ +@Scope("COMPOSITE") +public class SubtractServiceImpl implements SubtractService { + + public double subtract(double n1, double n2) { + return n1 - n2; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java new file mode 100644 index 0000000000..3336723dc0 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/ReadTestCase.java @@ -0,0 +1,261 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.xml; + +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.assembly.xml.CompositeProcessor; +import org.apache.tuscany.sca.binding.sca.impl.SCABindingFactoryImpl; +import org.apache.tuscany.sca.contribution.DefaultContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Test reading Java implementations. + * + * @version $Rev: 637129 $ $Date: 2008-03-14 08:11:59 -0700 (Fri, 14 Mar 2008) $ + */ +public class ReadTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private DefaultStAXArtifactProcessorExtensionPoint staxProcessors; + private ExtensibleStAXArtifactProcessor staxProcessor; + private AssemblyFactory assemblyFactory; + private SCABindingFactory scaBindingFactory; + private PolicyFactory policyFactory; + private InterfaceContractMapper mapper; + private SCADefinitionsDocumentProcessor scaDefnDocProcessor; + private IntentAttachPointTypeFactory intentAttachPointTypeFactory; + + @Override + public void setUp() throws Exception { + ModelFactoryExtensionPoint modelFactories = new DefaultModelFactoryExtensionPoint(); + assemblyFactory = new DefaultAssemblyFactory(); + modelFactories.addFactory(assemblyFactory); + scaBindingFactory = new SCABindingFactoryImpl(); + policyFactory = new DefaultPolicyFactory(); + modelFactories.addFactory(policyFactory); + mapper = new InterfaceContractMapperImpl(); + inputFactory = XMLInputFactory.newInstance(); + staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(modelFactories); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + intentAttachPointTypeFactory = new DefaultIntentAttachPointTypeFactory(); + + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + modelFactories.addFactory(javaImplementationFactory); + + CompositeProcessor compositeProcessor = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + staxProcessors.addArtifactProcessor(compositeProcessor); + + JavaImplementationProcessor javaProcessor = new JavaImplementationProcessor(modelFactories); + staxProcessors.addArtifactProcessor(javaProcessor); + + scaDefnDocProcessor = new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, inputFactory, policyFactory); + } + + @Override + public void tearDown() throws Exception { + inputFactory = null; + staxProcessors = null; + policyFactory = null; + assemblyFactory = null; + mapper = null; + } + + public void testReadComposite() throws Exception { + CompositeProcessor compositeProcessor = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeProcessor.read(reader); + assertNotNull(composite); + + CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, mapper, null); + compositeUtil.build(composite); + + } + + public void stestPolicyIntents() throws Exception { + ModelResolver resolver = new TestModelResolver(getClass().getClassLoader()); + + URL url = getClass().getResource("definitions.xml"); + URI uri = URI.create("definitions.xml"); + scaDefnDocProcessor.setDomainModelResolver(resolver); + SCADefinitions scaDefns = scaDefnDocProcessor.read(null, uri, url); + + CompositeProcessor compositeProcessor = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeProcessor.read(reader); + assertNotNull(composite); + + staxProcessor.resolve(scaDefns, resolver); + staxProcessor.resolve(composite, resolver); + + CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, mapper, null); + compositeUtil.build(composite); + + //intents are computed and aggregate intents from ancestor elements + assertEquals(((PolicySetAttachPoint)composite.getComponents().get(0)).getRequiredIntents().size(), 3); + assertEquals(((PolicySetAttachPoint)composite.getComponents().get(5)).getRequiredIntents().size(), 3); + + //assertEquals(((OperationsConfigurator)composite.getComponents().get(0)).getConfiguredOperations().isEmpty(), true); + //assertEquals(((OperationsConfigurator)composite.getComponents().get(5)).getConfiguredOperations().isEmpty(), false); + + + //test for proper aggregation of policy intents on implementation elements + for ( Intent intent : ((PolicySetAttachPoint)composite.getComponents().get(0).getImplementation()).getRequiredIntents() ) { + String intentName = intent.getName().getLocalPart(); + if ( !(intentName.equals("tuscanyIntent_1") || intentName.equals("tuscanyIntent_2") || + intentName.equals("tuscanyIntent_3")) ) { + fail(); + } + } + + for ( Intent intent : ((PolicySetAttachPoint)composite.getComponents().get(5)).getRequiredIntents() ) { + String intentName = intent.getName().getLocalPart(); + if ( !(intentName.equals("tuscanyIntent_1") || intentName.equals("tuscanyIntent_4") || + intentName.equals("tuscanyIntent_5")) ) { + fail(); + } + } + + //test for proper aggregation of policy intents and policysets on operations of implementation + OperationsConfigurator opConf = (OperationsConfigurator)composite.getComponents().get(5); + assertEquals(opConf.getConfiguredOperations().get(0).getRequiredIntents().size(), 4); + for ( Intent intent : opConf.getConfiguredOperations().get(0).getRequiredIntents()) { + String intentName = intent.getName().getLocalPart(); + if ( !(intentName.equals("tuscanyIntent_1") || intentName.equals("tuscanyIntent_4") || + intentName.equals("tuscanyIntent_5") || intentName.equals("tuscanyIntent_6") ) ) { + fail(); + } + } + + opConf = (OperationsConfigurator)composite.getComponents().get(6); + assertEquals(opConf.getConfiguredOperations().get(0).getRequiredIntents().size(), 3); + for ( Intent intent : opConf.getConfiguredOperations().get(0).getRequiredIntents()) { + String intentName = intent.getName().getLocalPart(); + if ( !(intentName.equals("tuscanyIntent_1") || intentName.equals("tuscanyIntent_4") || + intentName.equals("tuscanyIntent_6.qualified2") ) ) { + fail(); + } + } + + //new PrintUtil(System.out).print(composite); + } + + public void testPolicySets() throws Exception { + ModelResolver resolver = new TestModelResolver(getClass().getClassLoader()); + + URL url = getClass().getResource("definitions_with_policysets.xml"); + URI uri = URI.create("definitions_with_policysets.xml"); + scaDefnDocProcessor.setDomainModelResolver(resolver); + SCADefinitions scaDefns = scaDefnDocProcessor.read(null, uri, url); + + CompositeProcessor compositeProcessor = new CompositeProcessor(new DefaultContributionFactory(), assemblyFactory, policyFactory, staxProcessor); + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite composite = compositeProcessor.read(reader); + assertNotNull(composite); + + for ( Component component : composite.getComponents() ) { + for ( PolicySet policySet : scaDefns.getPolicySets() ) { + component.getApplicablePolicySets().add(policySet); + } + } + + staxProcessor.resolve(scaDefns, resolver); + staxProcessor.resolve(composite, resolver); + + CompositeBuilderImpl compositeUtil = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, mapper, null); + compositeUtil.build(composite); + + //test for determination of policysets for implementation + assertEquals(((PolicySetAttachPoint)composite.getComponents().get(0)).getPolicySets().size(), 1); + for ( PolicySet policySet : ((PolicySetAttachPoint)composite.getComponents().get(0).getImplementation()).getPolicySets() ) { + String policySetName = policySet.getName().getLocalPart(); + if ( !(policySetName.equals("tuscanyPolicySet_1")) ) { + fail(); + } + } + + assertEquals(((PolicySetAttachPoint)composite.getComponents().get(5)).getPolicySets().size(), 2); + for ( PolicySet policySet : ((PolicySetAttachPoint)composite.getComponents().get(5).getImplementation()).getPolicySets() ) { + String policySetName = policySet.getName().getLocalPart(); + if ( !(policySetName.equals("tuscanyPolicySet_1") || policySetName.equals("tuscanyPolicySet_2")) ) { + fail(); + } + } + + //test for computation of policysets on operations of implementation + OperationsConfigurator opConf = (OperationsConfigurator)composite.getComponents().get(5); + assertEquals(opConf.getConfiguredOperations().get(0).getPolicySets().size(), 3); + for ( PolicySet policySet : opConf.getConfiguredOperations().get(0).getPolicySets() ) { + String policySetName = policySet.getName().getLocalPart(); + if ( !(policySetName.equals("tuscanyPolicySet_1") || policySetName.equals("tuscanyPolicySet_2") + || policySetName.equals("tuscanyPolicySet_3")) ) { + fail(); + } + } + + opConf = (OperationsConfigurator)composite.getComponents().get(6); + assertEquals(opConf.getConfiguredOperations().get(0).getPolicySets().size(), 4); + for ( PolicySet policySet : opConf.getConfiguredOperations().get(0).getPolicySets() ) { + String policySetName = policySet.getName().getLocalPart(); + if ( !(policySetName.equals("tuscanyPolicySet_1") || policySetName.equals("tuscanyPolicySet_2") + || policySetName.equals("tuscanyPolicySet_3") + || policySetName.equals("tuscanyPolicySet_4")) ) { + fail(); + } + } + //new PrintUtil(System.out).print(composite); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.java new file mode 100644 index 0000000000..3de8c80bd4 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/TestModelResolver.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.implementation.java.xml; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A default implementation of an artifact resolver, based on a map. + * + * @version $Rev: 639650 $ $Date: 2008-03-21 06:05:33 -0800 (Fri, 21 Mar 2008) $ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map map = new HashMap(); + + private WeakReference classLoader; + + public TestModelResolver(ClassLoader classLoader) { + this.classLoader = new WeakReference(classLoader); + } + + public T resolveModel(Class modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else if (unresolved instanceof ClassReference) { + + // Load a class on demand + ClassReference classReference = (ClassReference)unresolved; + Class clazz; + try { + clazz = Class.forName(classReference.getClassName(), true, classLoader.get()); + } catch (ClassNotFoundException e) { + + // Return the unresolved object + return unresolved; + } + + // Store a new ClassReference wrapping the loaded class + resolved = new ClassReference(clazz); + map.put(resolved, resolved); + + // Return the resolved ClassReference + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved) { + return map.remove(resolved); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.java new file mode 100644 index 0000000000..0603553384 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/java/org/apache/tuscany/sca/implementation/java/xml/WriteTestCase.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.implementation.java.xml; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.xml.ComponentTypeProcessor; +import org.apache.tuscany.sca.assembly.xml.CompositeProcessor; +import org.apache.tuscany.sca.assembly.xml.ConstrainingTypeProcessor; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * Test writing Java implementations. + * + * @version $Rev: 638896 $ $Date: 2008-03-19 08:57:50 -0700 (Wed, 19 Mar 2008) $ + */ +public class WriteTestCase extends TestCase { + + private DefaultStAXArtifactProcessorExtensionPoint staxProcessors; + private ExtensibleStAXArtifactProcessor staxProcessor; + private AssemblyFactory factory; + private PolicyFactory policyFactory; + + @Override + public void setUp() throws Exception { + ModelFactoryExtensionPoint modelFactories = new DefaultModelFactoryExtensionPoint(); + factory = new DefaultAssemblyFactory(); + modelFactories.addFactory(factory); + policyFactory = new DefaultPolicyFactory(); + modelFactories.addFactory(policyFactory); + staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(modelFactories); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + modelFactories.addFactory(javaImplementationFactory); + + staxProcessors.addArtifactProcessor(new CompositeProcessor(null, factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(factory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ConstrainingTypeProcessor(factory, policyFactory, staxProcessor)); + + JavaImplementationProcessor javaProcessor = new JavaImplementationProcessor(modelFactories); + staxProcessors.addArtifactProcessor(javaProcessor); + } + + public void testReadWriteComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + Composite composite = staxProcessor.read(is, Composite.class); + assertNotNull(composite); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(composite, bos); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite b/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite new file mode 100644 index 0000000000..3d92031c65 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/Calculator.composite @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions.xml b/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions.xml new file mode 100644 index 0000000000..cddc134c2c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions.xml @@ -0,0 +1,100 @@ + + + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions_with_policysets.xml b/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions_with_policysets.xml new file mode 100644 index 0000000000..9147133d5d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java-xml/src/test/resources/org/apache/tuscany/sca/implementation/java/xml/definitions_with_policysets.xml @@ -0,0 +1,133 @@ + + + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + Sample Intent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java/.classpath b/branches/sca-android/tuscany-implementation-java/.classpath new file mode 100644 index 0000000000..a83c6d265d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/.classpath @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java/.project b/branches/sca-android/tuscany-implementation-java/.project new file mode 100644 index 0000000000..4b8a0dfdbf --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/.project @@ -0,0 +1,22 @@ + + tuscany-implementation-java + Parent POM defining settings that can be used across Tuscany + + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + tuscany-interface-java + tuscany-sca-api + tuscany-contribution + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-implementation-java/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-implementation-java/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..efa5a414bf --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:21:19 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-implementation-java/DISCLAIMER b/branches/sca-android/tuscany-implementation-java/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-implementation-java/LICENSE b/branches/sca-android/tuscany-implementation-java/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/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/branches/sca-android/tuscany-implementation-java/NOTICE b/branches/sca-android/tuscany-implementation-java/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-implementation-java/pom.xml b/branches/sca-android/tuscany-implementation-java/pom.xml new file mode 100644 index 0000000000..3130bd2890 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/pom.xml @@ -0,0 +1,50 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-implementation-java + Apache Tuscany SCA Java Implementation Model + + + + org.apache.tuscany.sca + tuscany-assembly + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-interface-java + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-sca-api + 2.0-incubating-SNAPSHOT + + + diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/BaseJavaImplementation.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/BaseJavaImplementation.java new file mode 100644 index 0000000000..ea3d9f0b59 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/BaseJavaImplementation.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java; + +import org.apache.tuscany.sca.assembly.Extensible; +import org.apache.tuscany.sca.assembly.Implementation; + +/** + * Represents a Java implementation. + * + * @version $Rev: 568902 $ $Date: 2007-08-23 02:32:29 -0700 (Thu, 23 Aug 2007) $ + */ +public interface BaseJavaImplementation extends Implementation, Extensible { + + /** + * Returns the name of the Java implementation class. + * + * @return the name of the Java implementation class + */ + String getName(); + + /** + * Sets the name of the Java implementation class. + * + * @param className the name of the Java implementation class + */ + void setName(String className); + + /** + * Returns the Java implementation class. + * + * @return the Java implementation class + */ + Class getJavaClass(); + + /** + * Sets the Java implementation class. + * + * @param javaClass the Java implementation class + */ + void setJavaClass(Class javaClass); + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/DefaultJavaImplementationFactory.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/DefaultJavaImplementationFactory.java new file mode 100644 index 0000000000..06cfabeb44 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/DefaultJavaImplementationFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java; + +/** + * A factory for the Java model. + */ +import org.apache.tuscany.sca.implementation.java.impl.JavaImplementationFactoryImpl; + +public class DefaultJavaImplementationFactory extends JavaImplementationFactoryImpl implements JavaImplementationFactory { + + public DefaultJavaImplementationFactory() { + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/IntrospectionException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/IntrospectionException.java new file mode 100644 index 0000000000..fac3f9a0dd --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/IntrospectionException.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.implementation.java; + +import java.lang.reflect.Member; + +/** + * Denotes a problem processing annotations on a POJO implementation + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IntrospectionException extends Exception { + private static final long serialVersionUID = -361025119035104470L; + private Member member; + + public IntrospectionException() { + } + + public IntrospectionException(String message) { + super(message); + } + + public IntrospectionException(String message, Member member) { + super(message); + this.member = member; + } + + public IntrospectionException(String message, Throwable cause) { + super(message, cause); + } + + public IntrospectionException(Throwable cause) { + super(cause); + } + + public Member getMember() { + return member; + } + + public void setMember(Member member) { + this.member = member; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementation.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementation.java new file mode 100644 index 0000000000..1b90be3043 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementation.java @@ -0,0 +1,197 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl; +import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; + +/** + * Represents a Java implementation. + * + * @version $Rev: 641555 $ $Date: 2008-03-26 12:31:08 -0800 (Wed, 26 Mar 2008) $ + */ +public interface JavaImplementation extends BaseJavaImplementation { + + /** + * Returns the constructor used to instantiate implementation instances. + * + * @return the constructor used to instantiate implementation instances + */ + JavaConstructorImpl getConstructor(); + + /** + * Sets the constructor used to instantiate implementation instances + * + * @param definition the constructor used to instantiate implementation instances + */ + void setConstructor(JavaConstructorImpl definition); + + /** + * Returns the component initializer method. + * + * @return the component initializer method + */ + Method getInitMethod(); + + /** + * Sets the component initializer method. + * + * @param initMethod the component initializer method + */ + void setInitMethod(Method initMethod); + + /** + * Returns the component destructor method. + * + * @return the component destructor method + */ + Method getDestroyMethod(); + + /** + * Sets the component destructor method. + * + * @param destroyMethod the component destructor method + */ + void setDestroyMethod(Method destroyMethod); + + /** + * Returns the resources injected into this implementation. + * + * @return + */ + Map getResources(); + + /** + * Returns the Java member used to inject a conversation ID. + * + * @return + */ + List getConversationIDMembers(); + + /** + * Sets the Java member used to inject a conversation ID. + * + * @param conversationIDMember + */ + void addConversationIDMember(Member conversationIDMember); + + /** + * Returns true if AllowsPassReference is set. + * + * @return true if AllowsPassByReference is set + */ + boolean isAllowsPassByReference(); + + /** + * @param allowsPassByReference the allowsPassByReference to set + */ + void setAllowsPassByReference(boolean allowsPassByReference); + + /** + * @return the allowsPassByReferenceMethods + */ + List getAllowsPassByReferenceMethods(); + + /** + * @param method + * @return + */ + boolean isAllowsPassByReference(Method method); + + /** + * @return the constructors + */ + Map getConstructors(); + + /** + * @return the eagerInit + */ + boolean isEagerInit(); + + /** + * @param eagerInit the eagerInit to set + */ + void setEagerInit(boolean eagerInit); + + /** + * @return the callbacks + */ + Map getCallbackMembers(); + + /** + * @return the properties + */ + Map getPropertyMembers(); + + /** + * @return the references + */ + Map getReferenceMembers(); + + /** + * @return the scope + */ + JavaScopeImpl getJavaScope(); + + /** + * @param scope the scope to set + */ + void setJavaScope(JavaScopeImpl scope); + + /** + * @return the maxAge + */ + long getMaxAge(); + + /** + * @param maxAge the maxAge to set + */ + void setMaxAge(long maxAge); + + /** + * @return the maxIdleTime + */ + long getMaxIdleTime(); + + /** + * @param maxIdleTime the maxIdleTime to set + */ + void setMaxIdleTime(long maxIdleTime); + + /** + * @return the map of a policy handler classnames + */ + Map> getPolicyHandlerClassNames(); + + /** + * @param map of policyhandler classnames + */ + void setPolicyHandlerClassNames(Map> policyHandlerClassNames); + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementationFactory.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementationFactory.java new file mode 100644 index 0000000000..f6695bde6d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/JavaImplementationFactory.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java; + +import java.util.List; + +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; + + +/** + * Factory for the Java model + * + * @version $Rev: 564429 $ $Date: 2007-08-09 16:49:11 -0700 (Thu, 09 Aug 2007) $ + */ +public interface JavaImplementationFactory { + + /** + * Creates a new Java implementation model. + * + * @return + */ + JavaImplementation createJavaImplementation(); + + /** + * Creates a new Java implementation model from an implementation class. + * + * @param implementationClass The implementation class to introspect. + * @return + */ + JavaImplementation createJavaImplementation(Class implementationClass) throws IntrospectionException; + + /** + * Creates the contents of a Java implementation model from an implementation class. + * + * @param implementationClass The implementation class to introspect. + * @return + */ + void createJavaImplementation(JavaImplementation javaImplementation, Class implementationClass) throws IntrospectionException; + + /** + * Registers the given visitor. + * + * @param visitor + */ + void addClassVisitor(JavaClassVisitor visitor); + + /** + * Deregisters the given visitor. + */ + void removeClassVisitor(JavaClassVisitor visitor); + + /** + * Returns the list of visitors. + * + * @return + */ + List getClassVisitors(); + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/BaseJavaImplementationImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/BaseJavaImplementationImpl.java new file mode 100644 index 0000000000..61fe2a1f0b --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/BaseJavaImplementationImpl.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.impl; + +import org.apache.tuscany.sca.assembly.impl.ImplementationImpl; +import org.apache.tuscany.sca.implementation.java.BaseJavaImplementation; + +/** + * Represents a Java implementation. + * + * @version $Rev: 637192 $ $Date: 2008-03-14 11:13:01 -0700 (Fri, 14 Mar 2008) $ + */ +abstract class BaseJavaImplementationImpl extends ImplementationImpl implements BaseJavaImplementation { + + private String className; + private Class javaClass; + + protected BaseJavaImplementationImpl() { + } + + public String getName() { + if (isUnresolved()) { + return className; + } else if (javaClass != null) { + return javaClass.getName(); + } else { + return null; + } + } + + public void setName(String className) { + if (!isUnresolved()) { + throw new IllegalStateException(); + } + this.className = className; + } + + public Class getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + if (this.className == null) { + this.className = javaClass.getName(); + } + } + + @Override + public int hashCode() { + return String.valueOf(getName()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof BaseJavaImplementation) { + if (getName() != null) { + return getName().equals(((BaseJavaImplementation)obj).getName()); + } else { + return ((BaseJavaImplementation)obj).getName() == null; + } + } else { + return false; + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaClassIntrospectorImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaClassIntrospectorImpl.java new file mode 100644 index 0000000000..5524c12c18 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaClassIntrospectorImpl.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper; + +/** + * An extensible Java class introspector implementation. + * + * @version $Rev: 584985 $ $Date: 2007-10-15 17:47:36 -0700 (Mon, 15 Oct 2007) $ + */ +public class JavaClassIntrospectorImpl { + + private List visitors; + + public JavaClassIntrospectorImpl(List visitors) { + this.visitors = visitors; + } + + /** + * JSR-250 PFD recommends the following guidelines for how annotations + * interact with inheritance in order to keep the resulting complexity in + * control: + *
    + *
  1. Class-level annotations only affect the class they annotate and + * their members, that is, its methods and fields. They never affect a + * member declared by a superclass, even if it is not hidden or overridden + * by the class in question. + *
  2. In addition to affecting the annotated class, class-level + * annotations may act as a shorthand for member-level annotations. If a + * member carries a specific member-level annotation, any annotations of the + * same type implied by a class-level annotation are ignored. In other + * words, explicit member-level annotations have priority over member-level + * annotations implied by a class-level annotation. + *
  3. The interfaces implemented by a class never contribute annotations + * to the class itself or any of its members. + *
  4. Members inherited from a superclass and which are not hidden or + * overridden maintain the annotations they had in the class that declared + * them, including member-level annotations implied by class-level ones. + *
  5. Member-level annotations on a hidden or overridden member are always + * ignored. + *
+ */ + public void introspectClass(JavaImplementation type, Class clazz) + throws IntrospectionException { + + for (JavaClassVisitor extension : visitors) { + //try { + extension.visitClass(clazz, type); + //} catch (Exception e) {} + } + + for (Constructor constructor : clazz.getConstructors()) { + for (JavaClassVisitor extension : visitors) { + extension.visitConstructor(constructor, type); + // Assuming the visitClass or visitConstructor will populate the + // type.getConstructors + JavaConstructorImpl definition = type.getConstructors().get(constructor); + if (definition != null) { + for (JavaParameterImpl p : definition.getParameters()) { + extension.visitConstructorParameter(p, type); + } + } + } + } + + Set fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz, true); + for (Field field : fields) { + for (JavaClassVisitor extension : visitors) { + extension.visitField(field, type); + } + } + + Set methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz, true); + for (Method method : methods) { + for (JavaClassVisitor processor : visitors) { + processor.visitMethod(method, type); + } + } + + Class superClass = clazz.getSuperclass(); + if (superClass != null) { + visitSuperClass(superClass, type); + } + + for (JavaClassVisitor extension : visitors) { + extension.visitEnd(clazz, type); + } + } + + private void visitSuperClass(Class clazz, JavaImplementation type) throws IntrospectionException { + if (!Object.class.equals(clazz)) { + for (JavaClassVisitor extension : visitors) { + extension.visitSuperClass(clazz, type); + } + clazz = clazz.getSuperclass(); + if (clazz != null) { + visitSuperClass(clazz, type); + } + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaConstructorImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaConstructorImpl.java new file mode 100644 index 0000000000..ff269713df --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaConstructorImpl.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.impl; + +import java.lang.reflect.Constructor; + +/** + * Hold injection information for the constructor used to instantiate a + * component implementation instance + * + * @version $Rev: 537426 $ $Date: 2007-05-12 07:05:05 -0700 (Sat, 12 May 2007) $ + */ +public class JavaConstructorImpl { + + private Constructor constructor; + private JavaParameterImpl[] parameters; + + public JavaConstructorImpl(Constructor constructor) { + this.constructor = constructor; + int size = constructor.getParameterTypes().length; + parameters = new JavaParameterImpl[size]; + for (int i = 0; i < size; i++) { + parameters[i] = new JavaParameterImpl(constructor, i); + } + } + + public Constructor getConstructor() { + return constructor; + } + + /** + * @return the parameters + */ + public JavaParameterImpl[] getParameters() { + return parameters; + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java new file mode 100644 index 0000000000..1ed5045429 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaElementImpl.java @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.impl; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +/** + * This class represents a java element such as a Package, Class, Constructor, + * Field, Method or Parameter. + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public class JavaElementImpl { + private AnnotatedElement anchor; + private ElementType elementType; + private Class type; + private Type genericType; + private int index = -1; + private String name; + private Class classifer; + + public JavaElementImpl(Package pkg) { + this.anchor = pkg; + this.elementType = ElementType.PACKAGE; + this.name = pkg.getName(); + } + + public JavaElementImpl(Class cls) { + this.anchor = cls; + this.elementType = ElementType.TYPE; + this.type = cls; + this.genericType = cls; + this.name = cls.getName(); + } + + public JavaElementImpl(Field field) { + this.anchor = field; + this.elementType = ElementType.FIELD; + this.type = field.getType(); + this.genericType = field.getGenericType(); + this.name = field.getName(); + } + + public JavaElementImpl(Constructor constructor, int index) { + this.anchor = constructor; + this.elementType = ElementType.PARAMETER; + this.type = constructor.getParameterTypes()[index]; + this.genericType = constructor.getGenericParameterTypes()[index]; + this.index = index; + this.name = ""; + } + + public JavaElementImpl(Method method, int index) { + this.anchor = method; + this.elementType = ElementType.PARAMETER; + this.type = method.getParameterTypes()[index]; + this.genericType = method.getGenericParameterTypes()[index]; + this.index = index; + this.name = ""; + } + + /** + * For testing purpose + * + * @param name + * @param type + * @param classifer TODO + * @param elementType + */ + public JavaElementImpl(String name, Class type, Class classifer) { + super(); + this.type = type; + this.name = name; + this.classifer = classifer; + } + + /** + * @return the anchor + */ + public AnnotatedElement getAnchor() { + return anchor; + } + + /** + * @return the elementType + */ + public ElementType getElementType() { + return elementType; + } + + /** + * @return the genericType + */ + public Type getGenericType() { + return genericType; + } + + /** + * @return the index + */ + public int getIndex() { + return index; + } + + /** + * @return the type + */ + public Class getType() { + return type; + } + + public Annotation[] getAnnotations() { + if (elementType == ElementType.PARAMETER) { + if (anchor instanceof Method) { + // We only care about the method-level annotations + return ((Method)anchor).getAnnotations(); + } + if (anchor instanceof Constructor) { + return ((Constructor)anchor).getParameterAnnotations()[index]; + } + } + return anchor.getAnnotations(); + } + + public T getAnnotation(Class annotationType) { + for (Annotation a : getAnnotations()) { + if (a.annotationType() == annotationType) { + return annotationType.cast(a); + } + } + return null; + } + + @Override + public String toString() { + return anchor.toString() + (elementType == ElementType.PARAMETER ? "[" + index + "]" : ""); + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((anchor == null) ? 0 : anchor.hashCode()); + result = PRIME * result + index; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final JavaElementImpl other = (JavaElementImpl)obj; + if (anchor == null) { + if (other.anchor != null) { + return false; + } + } else if (!anchor.equals(other.anchor)) { + return false; + } + if (index != other.index) { + return false; + } + return true; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the classifier + */ + public Class getClassifer() { + return classifer; + } + + /** + * @param classifer the classifier to set + */ + public void setClassifer(Class classifer) { + this.classifer = classifer; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationFactoryImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationFactoryImpl.java new file mode 100644 index 0000000000..35f8920b33 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationFactoryImpl.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.implementation.java.impl; + +/** + * A factory for the Java model. + */ +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; + +public abstract class JavaImplementationFactoryImpl implements JavaImplementationFactory { + + private List visitors = new ArrayList(); + private JavaClassIntrospectorImpl introspector; + + public JavaImplementationFactoryImpl() { + introspector = new JavaClassIntrospectorImpl(visitors); + } + + public JavaImplementation createJavaImplementation() { + JavaImplementation javaImplementation = new JavaImplementationImpl(); + return javaImplementation; + } + + public JavaImplementation createJavaImplementation(Class implementationClass) throws IntrospectionException { + JavaImplementation javaImplementation = createJavaImplementation(); + introspector.introspectClass(javaImplementation, implementationClass); + return javaImplementation; + } + + public void createJavaImplementation(JavaImplementation javaImplementation, Class implementationClass) throws IntrospectionException { + introspector.introspectClass(javaImplementation, implementationClass); + } + + public void addClassVisitor(JavaClassVisitor visitor) { + visitors.add(visitor); + } + + public void removeClassVisitor(JavaClassVisitor visitor) { + visitors.remove(visitor); + } + + public List getClassVisitors() { + return visitors; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationImpl.java new file mode 100644 index 0000000000..169f7fd6e3 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaImplementationImpl.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.implementation.java.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; + +/** + * A component type specialization for POJO implementations + * + * @version $$Rev: 604245 $$ $$Date: 2007-12-14 10:07:40 -0800 (Fri, 14 Dec 2007) $$ + */ +public class JavaImplementationImpl extends BaseJavaImplementationImpl implements JavaImplementation { + private JavaConstructorImpl constructorDefinition; + private Map constructors = new HashMap(); + private Method initMethod; + private Method destroyMethod; + private final Map resources = new HashMap(); + private final Map propertyMembers = new HashMap(); + private final Map referenceMembers = new HashMap(); + private final Map callbackMembers = new HashMap(); + private List conversationIDMember = new ArrayList(); + private boolean eagerInit; + private boolean allowsPassByReference; + private List allowsPassByReferenceMethods = new ArrayList(); + private long maxAge = -1; + private long maxIdleTime = -1; + private JavaScopeImpl scope = JavaScopeImpl.STATELESS; + private Map> policyHandlerClassNames = null; + + protected JavaImplementationImpl() { + super(); + } + + public JavaConstructorImpl getConstructor() { + return constructorDefinition; + } + + public void setConstructor(JavaConstructorImpl definition) { + this.constructorDefinition = definition; + } + + public Method getInitMethod() { + return initMethod; + } + + public void setInitMethod(Method initMethod) { + this.initMethod = initMethod; + } + + public Method getDestroyMethod() { + return destroyMethod; + } + + public void setDestroyMethod(Method destroyMethod) { + this.destroyMethod = destroyMethod; + } + + public Map getResources() { + return resources; + } + + public List getConversationIDMembers() { + return this.conversationIDMember; + } + + public void addConversationIDMember(Member conversationIDMember) { + this.conversationIDMember.add(conversationIDMember); + } + + public boolean isAllowsPassByReference() { + return allowsPassByReference; + } + + public void setAllowsPassByReference(boolean allowsPassByReference) { + this.allowsPassByReference = allowsPassByReference; + } + + public List getAllowsPassByReferenceMethods() { + return allowsPassByReferenceMethods; + } + + public boolean isAllowsPassByReference(Method method) { + return allowsPassByReference || allowsPassByReferenceMethods.contains(method); + } + + public Map getConstructors() { + return constructors; + } + + public boolean isEagerInit() { + return eagerInit; + } + + public void setEagerInit(boolean eagerInit) { + this.eagerInit = eagerInit; + } + + public Map getCallbackMembers() { + return callbackMembers; + } + + public Map getPropertyMembers() { + return propertyMembers; + } + + public Map getReferenceMembers() { + return referenceMembers; + } + + public JavaScopeImpl getJavaScope() { + return scope; + } + + public void setJavaScope(JavaScopeImpl scope) { + this.scope = scope; + } + + public long getMaxAge() { + return maxAge; + } + + public void setMaxAge(long maxAge) { + this.maxAge = maxAge; + } + + public long getMaxIdleTime() { + return maxIdleTime; + } + + public void setMaxIdleTime(long maxIdleTime) { + this.maxIdleTime = maxIdleTime; + } + + public Map> getPolicyHandlerClassNames() { + return policyHandlerClassNames; + } + + public void setPolicyHandlerClassNames(Map> policyHandlerClassNames) { + this.policyHandlerClassNames = policyHandlerClassNames; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaParameterImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaParameterImpl.java new file mode 100644 index 0000000000..cf1bf096dd --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaParameterImpl.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.implementation.java.impl; + +import java.lang.reflect.Constructor; + +/** + * @version $Rev: 537426 $ $Date: 2007-05-12 07:05:05 -0700 (Sat, 12 May 2007) $ + */ +public class JavaParameterImpl extends JavaElementImpl { + /** + * @param constructor + * @param index + */ + public JavaParameterImpl(Constructor constructor, int index) { + super(constructor, index); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaResourceImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaResourceImpl.java new file mode 100644 index 0000000000..fb59566222 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaResourceImpl.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.impl; + + +/** + * A resource dependency declared by a Java component implementation + * + * @version $Rev: 537426 $ $Date: 2007-05-12 07:05:05 -0700 (Sat, 12 May 2007) $ + */ +public class JavaResourceImpl { + private JavaElementImpl element; + private String mappedName; + private boolean optional; + + public JavaResourceImpl(JavaElementImpl element) { + this.element = element; + } + + /** + * The name of the resource + * + * @return the name of the resource + */ + public String getName() { + return element.getName(); + } + + /** + * Returns the URI of the resource + * + * @return the URI of the resource + */ + public String getMappedName() { + return mappedName; + } + + /** + * Sets the resource URI + */ + public void setMappedName(String mappedName) { + this.mappedName = mappedName; + } + + /** + * If true, the resource is optional + * + * @return true if the resource is optional + */ + public boolean isOptional() { + return optional; + } + + /** + * Sets whether the resource is optional + */ + public void setOptional(boolean optional) { + this.optional = optional; + } + + /** + * @return the element + */ + public JavaElementImpl getElement() { + return element; + } + + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaScopeImpl.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaScopeImpl.java new file mode 100644 index 0000000000..0b80b59600 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/impl/JavaScopeImpl.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.implementation.java.impl; + +/** + * The default implementation scopes supported by assemblies. + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class JavaScopeImpl { + public static final JavaScopeImpl STATELESS = new JavaScopeImpl("STATELESS"); + public static final JavaScopeImpl REQUEST = new JavaScopeImpl("REQUEST"); + public static final JavaScopeImpl SESSION = new JavaScopeImpl("SESSION"); + public static final JavaScopeImpl CONVERSATION = new JavaScopeImpl("CONVERSATION"); + public static final JavaScopeImpl COMPOSITE = new JavaScopeImpl("COMPOSITE"); + public static final JavaScopeImpl SYSTEM = new JavaScopeImpl("SYSTEM"); + public static final JavaScopeImpl UNDEFINED = new JavaScopeImpl("UNDEFINED"); + + private String scope; + + public JavaScopeImpl(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 JavaScopeImpl scope1 = (JavaScopeImpl) 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/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java new file mode 100644 index 0000000000..fac5643eed --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/JavaClassVisitor.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; + +/** + * Implementations process class-level metadata, typically parsing annotations + * and updating the corresponding ComponentType. A processor + * may, for example, create a Property which is responsible for injecting a + * complex type on a component implementation instance when it is instantiated. + *

Processors will receive callbacks as the implementation class is walked + * while evaluating an assembly. It is the responsibility of the parser to + * determine whether to perform an action during the callback. + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public interface JavaClassVisitor { + + /** + * A callback received when the component implementation class is first + * loaded + * + * @param clazz the component implementation class + * @param type the incomplete component type associated with the + * implementation class + * @throws IntrospectionException if an error is encountered while processing + * metadata + */ + void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException; + + /** + * A callback received as the component implementation class hierarchy is + * evaluated + * + * @param clazz the superclass in the component implmentation's class + * hierarchy + * @param type the incomplete component type associated with the + * implementation class + * @throws IntrospectionException if an error is encountered while processing + * metadata + */ + void visitSuperClass(Class clazz, JavaImplementation type) throws IntrospectionException; + + /** + * A callback received as the component implementation's public and + * protected methods are evaluated + * + * @param method the current public or protected method being evaluated + * @param type the incomplete component type associated with the + * implementation class + * @throws IntrospectionException if an error is encountered while processing + * metadata + */ + void visitMethod(Method method, JavaImplementation type) throws IntrospectionException; + + /** + * A callback received as the component implementation's constructor used + * for instantiation by the runtime is evaluated. If an implementation + * contains more than one constructor, the constructor passed to the + * callback will be chosen according to the algorithm described in the SCA + * Java Client and Implementation Model Specification. + * + * @param constructor the constructor used for instantiating component + * implementation instances + * @param type the incomplete component type associated with the + * implementation class + * @throws IntrospectionException if an error is encountered while processing + * metadata + */ + void visitConstructor(Constructor constructor, JavaImplementation type) throws IntrospectionException; + + /** + * @param parameter + * @param type + * @throws IntrospectionException + */ + void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) throws IntrospectionException; + + /** + * A callback received as the component implementation's public and + * protected fields are evaluated + * + * @param field the current public or protected field being evaluated + * @param type the incomplete component type associated with the + * implementation class + * @throws IntrospectionException if an error is encountered while processing + * metadata + */ + void visitField(Field field, JavaImplementation type) throws IntrospectionException; + + /** + * The final callback received when all other callbacks during evaluation of + * the component implementation have been issued + * + * @param clazz the component implementation class + * @param type the incomplete component type associated with the + * implementation class + * @throws IntrospectionException if an error is encountered while processing + * metadata + */ + void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException; + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java new file mode 100644 index 0000000000..8af1256a17 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessor.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; + +/** + * Base class for ImplementationProcessors that handle annotations that add + * Properties. + * + * @version $Rev: 584985 $ $Date: 2007-10-15 17:47:36 -0700 (Mon, 15 Oct 2007) $ + */ +public abstract class AbstractPropertyProcessor extends BaseJavaClassVisitor { + private final Class annotationClass; + + protected AbstractPropertyProcessor(AssemblyFactory assemblyFactory, Class annotationClass) { + super(assemblyFactory); + this.annotationClass = annotationClass; + } + + private boolean removeProperty(JavaElementImpl prop, JavaImplementation type) { + if(prop==null) { + return false; + } + List props = type.getProperties(); + for(int i=0;i properties = type.getPropertyMembers(); + JavaElementImpl prop = properties.get(name); + // Setter override field + if (prop != null && prop.getElementType() != ElementType.FIELD) { + throw new DuplicatePropertyException(name); + } + + removeProperty(prop, type); + + JavaElementImpl element = new JavaElementImpl(method, 0); + Property property = createProperty(name, element); + + // add databinding available as annotations, as extensions + + initProperty(property, annotation); + type.getProperties().add(property); + properties.put(name, element); + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + + A annotation = field.getAnnotation(annotationClass); + if (annotation == null) { + return; + } + + String name = getName(annotation); + if (name == null) { + name = ""; + } + if ("".equals(name) || name.equals(field.getType().getName())) { + name = field.getName(); + } + + Map properties = type.getPropertyMembers(); + JavaElementImpl prop = properties.get(name); + // Setter override field + if (prop != null && prop.getElementType() == ElementType.FIELD) { + throw new DuplicatePropertyException(name); + } + + if (prop == null) { + JavaElementImpl element = new JavaElementImpl(field); + Property property = createProperty(name, element); + initProperty(property, annotation); + type.getProperties().add(property); + properties.put(name, element); + } + } + + @Override + public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) + throws IntrospectionException { + + Map properties = type.getPropertyMembers(); + A annotation = parameter.getAnnotation(annotationClass); + if (annotation != null) { + String name = getName(annotation); + if (name == null) { + name = parameter.getType().getName(); + } + if (!"".equals(name) && !"".equals(parameter.getName()) && !name.equals(parameter.getName())) { + throw new InvalidConstructorException("Mismatched property name: " + parameter); + } + if ("".equals(name) && "".equals(parameter.getName())) { + throw new InvalidPropertyException("Missing property name: " + parameter); + } + if ("".equals(name)) { + name = parameter.getName(); + } + + JavaElementImpl prop = properties.get(name); + // Setter override field + if (prop != null && prop.getElementType() != ElementType.FIELD) { + throw new DuplicatePropertyException(name); + } + removeProperty(prop, type); + + parameter.setName(name); + parameter.setClassifer(annotationClass); + Property property = createProperty(name, parameter); + initProperty(property, annotation); + type.getProperties().add(property); + properties.put(name, parameter); + } + } + + protected abstract String getName(A annotation); + + protected abstract void initProperty(Property property, A annotation) throws IntrospectionException; + + @SuppressWarnings("unchecked") + protected Property createProperty(String name, JavaElementImpl element) throws IntrospectionException { + + Property property = assemblyFactory.createProperty(); + property.setName(name); + Class baseType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + property.setXSDType(JavaXMLMapper.getXMLType(baseType)); + + Class javaType = element.getType(); + if (javaType.isArray() || Collection.class.isAssignableFrom(javaType)) { + property.setMany(true); + } + return property; + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java new file mode 100644 index 0000000000..c6ac1cd69c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessor.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.osoa.sca.annotations.AllowsPassByReference; + +/** + * Processes {@link AllowsPassByReference} on an implementation + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class AllowsPassByReferenceProcessor extends BaseJavaClassVisitor { + + public AllowsPassByReferenceProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + type.setAllowsPassByReference(clazz.isAnnotationPresent(AllowsPassByReference.class)); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + boolean pbr = method.isAnnotationPresent(AllowsPassByReference.class); + if (pbr) { + type.getAllowsPassByReferenceMethods().add(method); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.java new file mode 100644 index 0000000000..3928f59482 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AmbiguousConstructorException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when constructor parameters cannot be unambiguously resolved to a property or reference + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class AmbiguousConstructorException extends IntrospectionException { + private static final long serialVersionUID = 3662860753837091880L; + + public AmbiguousConstructorException(String message) { + super(message); + } + + public AmbiguousConstructorException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java new file mode 100644 index 0000000000..79f90baece --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/BaseJavaClassVisitor.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; + +/** + * A convenience class for annotation processors which alleviates the need to + * implement unused callbacks + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public abstract class BaseJavaClassVisitor implements JavaClassVisitor { + protected AssemblyFactory assemblyFactory; + + protected BaseJavaClassVisitor(AssemblyFactory factory) { + this.assemblyFactory = factory; + } + + public void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + } + + public void visitSuperClass(Class clazz, JavaImplementation type) throws IntrospectionException { + } + + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + } + + public void visitConstructor(Constructor constructor, JavaImplementation type) throws IntrospectionException { + } + + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + } + + public void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + } + + public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) throws IntrospectionException { + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ComponentNameProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ComponentNameProcessor.java new file mode 100644 index 0000000000..6acaa3e17d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ComponentNameProcessor.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.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.osoa.sca.annotations.ComponentName; + +/** + * Processes {@link @ComponentName} annotations on a component implementation and adds + * a {@link JavaMappedProperty} to the component type which will be used to + * inject the appropriate component name. + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ComponentNameProcessor extends BaseJavaClassVisitor { + + public ComponentNameProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + if (method.getAnnotation(ComponentName.class) == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalContextException("ComponentName setter must have one parameter", method); + } + Class paramType = method.getParameterTypes()[0]; + String name = JavaIntrospectionHelper.toPropertyName(method.getName()); + if (String.class.equals(paramType)) { + JavaElementImpl element = new JavaElementImpl(method, 0); + element.setName(name); + element.setClassifer(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + JavaResourceImpl resource = new JavaResourceImpl(element); + type.getResources().put(resource.getName(), resource); + } else { + throw new IllegalContextException(paramType.getName()); + } + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + if (field.getAnnotation(ComponentName.class) == null) { + return; + } + Class paramType = field.getType(); + if (String.class.equals(paramType)) { + JavaElementImpl element = new JavaElementImpl(field); + element.setClassifer(Resource.class); + JavaResourceImpl resource = new JavaResourceImpl(element); + type.getResources().put(resource.getName(), resource); + } else { + throw new IllegalContextException(paramType.getName()); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java new file mode 100644 index 0000000000..739445c90a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessor.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; + +/** + * Handles processing of a constructor decorated with + * {@link org.osoa.sca.annotations.Constructor} + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +@SuppressWarnings("unchecked") +public class ConstructorProcessor extends BaseJavaClassVisitor { + + public ConstructorProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + Constructor[] ctors = clazz.getConstructors(); + boolean found = false; + for (Constructor constructor : ctors) { + JavaConstructorImpl definition = new JavaConstructorImpl(constructor); + type.getConstructors().put(constructor, definition); + if (constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) { + if (found) { + throw new DuplicateConstructorException("Multiple constructors marked with @Constructor", constructor); + } + found = true; + type.setConstructor(definition); + } + } + } + + @Override + public void visitConstructor(Constructor constructor, JavaImplementation type) + throws IntrospectionException { + org.osoa.sca.annotations.Constructor annotation = constructor + .getAnnotation(org.osoa.sca.annotations.Constructor.class); + if (annotation == null) { + return; + } + JavaConstructorImpl definition = type.getConstructor(); + if (definition == null) { + definition = new JavaConstructorImpl(constructor); + type.setConstructor(definition); + } + JavaParameterImpl[] parameters = definition.getParameters(); + String[] value = annotation.value(); + boolean isDefault = value.length == 0 || (value.length == 1 && "".equals(value[0])); + if (!isDefault && value.length != parameters.length) { + throw new InvalidConstructorException("Invalid Nubmer of names in @Constructor"); + } + for (int i = 0; i < parameters.length; i++) { + parameters[i].setName(i < value.length ? value[i] : ""); + } + type.setConstructor(definition); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java new file mode 100644 index 0000000000..1c34a50762 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessor.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.annotations.Context; + +/** + * Processes {@link @Context} annotations on a component implementation and adds + * a {@link JavaMappedProperty} to the component type which will be used to + * inject the appropriate context + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ContextProcessor extends BaseJavaClassVisitor { + + public ContextProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + if (method.getAnnotation(Context.class) == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalContextException("Context setter must have one parameter", method); + } + Class paramType = method.getParameterTypes()[0]; + String name = JavaIntrospectionHelper.toPropertyName(method.getName()); + if (ComponentContext.class.equals(paramType) || RequestContext.class.equals(paramType)) { + JavaElementImpl element = new JavaElementImpl(method, 0); + element.setName(name); + element.setClassifer(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + JavaResourceImpl resource = new JavaResourceImpl(element); + type.getResources().put(resource.getName(), resource); + } else { + throw new UnknownContextTypeException(paramType.getName()); + } + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + if (field.getAnnotation(Context.class) == null) { + return; + } + Class paramType = field.getType(); + if (ComponentContext.class.equals(paramType) || RequestContext.class.equals(paramType)) { + JavaElementImpl element = new JavaElementImpl(field); + element.setClassifer(Resource.class); + JavaResourceImpl resource = new JavaResourceImpl(element); + type.getResources().put(resource.getName(), resource); + } else { + throw new UnknownContextTypeException(paramType.getName()); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessor.java new file mode 100644 index 0000000000..2db58006e6 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessor.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.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; +import org.osoa.sca.annotations.ConversationID; + +/** + * Processes {@link @ConversationID} annotations on a component implementation and adds + * a {@link JavaMappedProperty} to the component type which will be used to + * inject the appropriate conversationId + */ +public class ConversationIDProcessor extends BaseJavaClassVisitor { + + public ConversationIDProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + if (method.getAnnotation(ConversationID.class) == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalContextException("ConversationID setter must have one parameter", method); + } + String name = JavaIntrospectionHelper.toPropertyName(method.getName()); + JavaElementImpl element = new JavaElementImpl(method, 0); + element.setName(name); + element.setClassifer(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + JavaResourceImpl resource = new JavaResourceImpl(element); + type.getResources().put(resource.getName(), resource); + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + if (field.getAnnotation(ConversationID.class) == null) { + return; + } + JavaElementImpl element = new JavaElementImpl(field); + element.setClassifer(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + JavaResourceImpl resource = new JavaResourceImpl(element); + type.getResources().put(resource.getName(), resource); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java new file mode 100644 index 0000000000..8ad0b7cc43 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessor.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.osoa.sca.annotations.ConversationAttributes; +import org.osoa.sca.annotations.ConversationID; +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev: 638894 $ $Date: 2008-03-19 08:55:45 -0700 (Wed, 19 Mar 2008) $ + */ +public class ConversationProcessor extends BaseJavaClassVisitor { + private static final String SECONDS = " SECONDS"; + private static final String MINUTES = " MINUTES"; + private static final String HOURS = " HOURS"; + private static final String DAYS = " DAYS"; + private static final String YEARS = " YEARS"; + + public ConversationProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + + + ConversationAttributes conversation = clazz.getAnnotation(ConversationAttributes.class); + if (conversation == null) { + return; + } + Scope scope = clazz.getAnnotation(Scope.class); + if (scope == null) { + // implicitly assume conversation + type.setJavaScope(org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl.CONVERSATION); + } else if (conversation != null) { + long maxAge; + long maxIdleTime; + String maxAgeVal = conversation.maxAge(); + String maxIdleTimeVal = conversation.maxIdleTime(); + try { + if (maxAgeVal.length() > 0) { + maxAge = convertTimeMillis(maxAgeVal); + type.setMaxAge(maxAge); + } + } catch (NumberFormatException e) { + throw new InvalidConversationalImplementation("Invalid maximum age", e); + } + try { + if (maxIdleTimeVal.length() > 0) { + maxIdleTime = convertTimeMillis(maxIdleTimeVal); + type.setMaxIdleTime(maxIdleTime); + } + } catch (NumberFormatException e) { + throw new InvalidConversationalImplementation("Invalid maximum idle time", e); + } + } + + } + + @Override + public void visitMethod(Method method, + JavaImplementation type) throws IntrospectionException { + ConversationID conversationID = method.getAnnotation(ConversationID.class); + if (conversationID == null) { + return; + } + type.addConversationIDMember(method); + } + + @Override + public void visitField(Field field, + JavaImplementation type) throws IntrospectionException { + ConversationID conversationID = field.getAnnotation(ConversationID.class); + if (conversationID == null) { + return; + } + type.addConversationIDMember(field); + } + + protected long convertTimeMillis(String expr) throws NumberFormatException { + expr = expr.trim().toUpperCase(); + int i = expr.lastIndexOf(SECONDS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 1000; + } + i = expr.lastIndexOf(MINUTES); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 60000; + } + + i = expr.lastIndexOf(HOURS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 3600000; + } + i = expr.lastIndexOf(DAYS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 86400000; + } + i = expr.lastIndexOf(YEARS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 31556926000L; + } + return Long.parseLong(expr) * 1000; // assume seconds if no suffix + // specified + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java new file mode 100644 index 0000000000..9e0ce3e427 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.osoa.sca.annotations.Destroy; + +/** + * Processes the {@link @Destroy} annotation on a component implementation and + * updates the component type with the decorated destructor method + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class DestroyProcessor extends BaseJavaClassVisitor { + + public DestroyProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + Destroy annotation = method.getAnnotation(Destroy.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 0) { + throw new IllegalDestructorException("Destructor must not have argments", method); + } + if (type.getDestroyMethod() != null) { + throw new DuplicateDestructorException("More than one destructor found on implementation"); + } + if (Modifier.isProtected(method.getModifiers())) { + method.setAccessible(true); + } + type.setDestroyMethod(method); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java new file mode 100644 index 0000000000..dd879e66fa --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateConstructorException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when more than one component implementation constructor is annotated with {@link + * org.osoa.sca.annotations.Constructor} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class DuplicateConstructorException extends IntrospectionException { + private static final long serialVersionUID = -5926763756570552986L; + + public DuplicateConstructorException(String message) { + super(message); + } + + public DuplicateConstructorException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.java new file mode 100644 index 0000000000..c137de4e4a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateDestructorException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when an implementation is annotated multiple times with {@link org.osoa.sca.annotations.Destroy} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class DuplicateDestructorException extends IntrospectionException { + private static final long serialVersionUID = -7474912510114895203L; + + public DuplicateDestructorException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.java new file mode 100644 index 0000000000..962bd5a5d3 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateInitException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when an implementation is annotated multiple times with {@link @org.osoa.sca.annotations.Init} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class DuplicateInitException extends IntrospectionException { + private static final long serialVersionUID = -6282935288115512057L; + + public DuplicateInitException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicatePropertyException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicatePropertyException.java new file mode 100644 index 0000000000..2fa4428a1f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicatePropertyException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when an implementation has more than one property injection site with the same name + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class DuplicatePropertyException extends IntrospectionException { + private static final long serialVersionUID = 5536415875694904037L; + + public DuplicatePropertyException(String message) { + super(message); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.java new file mode 100644 index 0000000000..20ec93448c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateReferenceException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when an implementation has more than one reference injection site with the same name + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class DuplicateReferenceException extends IntrospectionException { + private static final long serialVersionUID = 907910648213477158L; + + public DuplicateReferenceException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.java new file mode 100644 index 0000000000..9864402b12 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DuplicateResourceException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when an implementation has more than one resource injection site with the same name + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class DuplicateResourceException extends IntrospectionException { + + private static final long serialVersionUID = 1619276459330463299L; + + public DuplicateResourceException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java new file mode 100644 index 0000000000..6b6f6579d9 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessor.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.osoa.sca.annotations.EagerInit; + +/** + * Handles processing of {@link org.osoa.sca.annotations.EagerInit} + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class EagerInitProcessor extends BaseJavaClassVisitor { + + public EagerInitProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitClass(Class clazz, + JavaImplementation type) throws IntrospectionException { + super.visitClass(clazz, type); + EagerInit annotation = clazz.getAnnotation(EagerInit.class); + if (annotation == null) { + Class superClass = clazz.getSuperclass(); + while (!Object.class.equals(superClass)) { + annotation = superClass.getAnnotation(EagerInit.class); + if (annotation != null) { + break; + } + superClass = superClass.getSuperclass(); + } + if (annotation == null) { + return; + } + } + type.setEagerInit(true); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java new file mode 100644 index 0000000000..277313606f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessor.java @@ -0,0 +1,605 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllInterfaces; +import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllPublicAndProtectedFields; +import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods; +import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.toPropertyName; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Context; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Service; + +/** + * Heuristically evaluates an un-annotated Java implementation type to determine + * services, references, and properties according to the algorithm described in + * the SCA Java Client and Implementation Model Specification

TODO + * Implement:

When no service interface is annotated, need to calculate a + * single service comprising all public methods that are not reference or + * property injection sites. If that service can be exactly mapped to an + * interface implemented by the class then the service interface will be defined + * in terms of that interface. + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public class HeuristicPojoProcessor extends BaseJavaClassVisitor { + private JavaInterfaceFactory javaFactory; + + public HeuristicPojoProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory) { + super(assemblyFactory); + this.javaFactory = javaFactory; + } + + @Override + public void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + List services = type.getServices(); + if (services.isEmpty()) { + // heuristically determine the service + /** + * The following is quoted from Java Specification 1.2.1.3. Introspecting services offered by a Java implementation + * In the cases described below, the services offered by a Java implementation class may be determined + * through introspection, eliding the need to specify them using @Service. The following algorithm is used + * to determine how services are introspected from an implementation class: + * + * If the interfaces of the SCA services are not specified with the @Service annotation on the + * implementation class, it is assumed that all implemented interfaces that have been annotated + * as @Remotable are the service interfaces provided by the component. If none of the implemented + * interfaces is remotable, then by default the implementation offers a single service whose type + * is the implementation class. + */ + Set interfaces = getAllInterfaces(clazz); + for (Class i : interfaces) { + if (i.isAnnotationPresent(Remotable.class)) { + addService(type, i); + } + } + if (services.isEmpty()) { + // class is the interface + addService(type, clazz); + } + } + Set methods = getAllUniquePublicProtectedMethods(clazz, false); + if (!type.getReferenceMembers().isEmpty() || !type.getPropertyMembers().isEmpty()) { + // references and properties have been explicitly defined + // if (type.getServices().isEmpty()) { + // calculateServiceInterface(clazz, type, methods); + // if (type.getServices().isEmpty()) { + // throw new ServiceTypeNotFoundException(clazz.getName()); + // } + // } + evaluateConstructor(type, clazz); + return; + } + calcPropRefs(methods, services, type, clazz); + evaluateConstructor(type, clazz); + } + + private void addService(JavaImplementation type, Class clazz) throws IntrospectionException { + try { + org.apache.tuscany.sca.assembly.Service service = createService(clazz); + type.getServices().add(service); + } catch (InvalidInterfaceException e) { + throw new IntrospectionException(e); + } + } + + private boolean isPublicSetter(Method method) { + return method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers()) + && method.getName().startsWith("set") + && method.getReturnType() == void.class; + } + + private boolean isProtectedSetter(Method method) { + return method.getParameterTypes().length == 1 && Modifier.isProtected(method.getModifiers()) + && method.getName().startsWith("set") + && method.getReturnType() == void.class; + } + + private void calcPropRefs(Set methods, + List services, + JavaImplementation type, + Class clazz) throws IntrospectionException { + // heuristically determine the properties references + // make a first pass through all public methods with one param + Set setters = new HashSet(); + for (Method method : methods) { + if (!isPublicSetter(method)) { + continue; + } + if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) { + continue; + } + if (!isInServiceInterface(method, services)) { + // Not part of the service interface + String name = toPropertyName(method.getName()); + setters.add(name); + // avoid duplicate property or ref names + if (!type.getPropertyMembers().containsKey(name) && !type.getReferenceMembers().containsKey(name)) { + Class param = method.getParameterTypes()[0]; + Type genericType = method.getGenericParameterTypes()[0]; + if (isReferenceType(param, genericType)) { + type.getReferences().add(createReference(name, param)); + type.getReferenceMembers().put(name, new JavaElementImpl(method, 0)); + } else { + type.getProperties().add(createProperty(name, param)); + type.getPropertyMembers().put(name, new JavaElementImpl(method, 0)); + } + } + } + } + // second pass for protected methods with one param + for (Method method : methods) { + if (!isProtectedSetter(method)) { + continue; + } + if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) { + continue; + } + Class param = method.getParameterTypes()[0]; + String name = toPropertyName(method.getName()); + setters.add(name); + // avoid duplicate property or ref names + if (isReferenceType(param, method.getGenericParameterTypes()[0])) { + if (!type.getReferenceMembers().containsKey(name)) { + type.getReferences().add(createReference(name, param)); + type.getReferenceMembers().put(name, new JavaElementImpl(method, 0)); + } + } else { + if (!type.getPropertyMembers().containsKey(name)) { + type.getProperties().add(createProperty(name, param)); + type.getPropertyMembers().put(name, new JavaElementImpl(method, 0)); + } + } + } + + // Public or protected fields unless there is a public or protected + // setter method + // for the same name + Set fields = getAllPublicAndProtectedFields(clazz, false); + for (Field field : fields) { + if (field.isAnnotationPresent(Callback.class) || field.isAnnotationPresent(Context.class)) { + continue; + } + if (setters.contains(field.getName())) { + continue; + } + String name = field.getName(); + Class paramType = field.getType(); + if (isReferenceType(paramType, field.getGenericType())) { + if (!type.getReferenceMembers().containsKey(name)) { + type.getReferences().add(createReference(name, paramType)); + type.getReferenceMembers().put(name, new JavaElementImpl(field)); + } + } else { + if (!type.getPropertyMembers().containsKey(name)) { + type.getProperties().add(createProperty(name, paramType)); + type.getPropertyMembers().put(name, new JavaElementImpl(field)); + } + } + } + } + + /** + * Determines the constructor to use based on the component type's + * references and properties + * + * @param type the component type + * @param clazz the implementation class corresponding to the component type + * @throws NoConstructorException if no suitable constructor is found + * @throws AmbiguousConstructorException if the parameters of a constructor + * cannot be unambiguously mapped to references and properties + */ + @SuppressWarnings("unchecked") + private void evaluateConstructor(JavaImplementation type, Class clazz) throws IntrospectionException { + // determine constructor if one is not annotated + JavaConstructorImpl definition = type.getConstructor(); + Constructor constructor; + boolean explict = false; + if (definition != null && definition.getConstructor() + .isAnnotationPresent(org.osoa.sca.annotations.Constructor.class)) { + // the constructor was already defined explicitly + return; + } else if (definition != null) { + explict = true; + constructor = definition.getConstructor(); + } else { + // no definition, heuristically determine constructor + Constructor[] constructors = clazz.getConstructors(); + if (constructors.length == 0) { + throw new NoConstructorException("No public constructor for class"); + } else if (constructors.length == 1) { + // Only one constructor, take it + constructor = constructors[0]; + } else { + // FIXME multiple constructors, none yet done + Constructor selected = null; + int sites = type.getPropertyMembers().size() + type.getReferenceMembers().size(); + for (Constructor ctor : constructors) { + if (ctor.getParameterTypes().length == 0) { + selected = ctor; + } + if (ctor.getParameterTypes().length == sites) { + // TODO finish + // selected = constructor; + // select constructor + // break; + } + } + if (selected == null) { + throw new NoConstructorException(); + } + constructor = selected; + definition = type.getConstructors().get(selected); + type.setConstructor(definition); + // return; + } + definition = type.getConstructors().get(constructor); + type.setConstructor(definition); + } + JavaParameterImpl[] parameters = definition.getParameters(); + if (parameters.length == 0) { + return; + } + Map props = type.getPropertyMembers(); + Map refs = type.getReferenceMembers(); + Annotation[][] annotations = constructor.getParameterAnnotations(); + if (!explict) { + // the constructor wasn't defined by an annotation, so check to see + // if any of the params have an annotation + // which we can impute as explicitly defining the constructor, e.g. + // @Property, @Reference, or @Autowire + explict = injectionAnnotationsPresent(annotations); + } + if (explict) { + for (int i = 0; i < parameters.length; i++) { + if (isAnnotated(parameters[i])) { + continue; + } else if (!findReferenceOrProperty(parameters[i], props, refs)) { + throw new AmbiguousConstructorException(parameters[i].toString()); + } + } + } else { + if (!areUnique(parameters)) { + throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor"); + } + if (!calcPropRefUniqueness(props.values(), refs.values())) { + throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor"); + } + if (!(props.isEmpty() && refs.isEmpty())) { + calcParamNames(parameters, props, refs); + } else { + heuristicParamNames(type, parameters); + + } + } + } + + private void calcParamNames(JavaParameterImpl[] parameters, + Map props, + Map refs) throws AmbiguousConstructorException { + // the constructor param types must unambiguously match defined + // reference or property types + for (JavaParameterImpl param : parameters) { + if (!findReferenceOrProperty(param, props, refs)) { + throw new AmbiguousConstructorException(param.getName()); + } + } + } + + private void heuristicParamNames(JavaImplementation type, JavaParameterImpl[] parameters) + throws IntrospectionException { + // heuristically determine refs and props from the parameter types + for (JavaParameterImpl p : parameters) { + String name = p.getType().getSimpleName().toLowerCase(); + if (isReferenceType(p.getType(), p.getGenericType())) { + type.getReferences().add(createReference(name, p.getType())); + p.setClassifer(Reference.class); + type.getReferenceMembers().put(name, p); + } else { + type.getProperties().add(createProperty(name, p.getType())); + p.setClassifer(Property.class); + type.getPropertyMembers().put(name, p); + } + p.setName(name); + } + } + + private static boolean areUnique(Class[] collection) { + Set set = new HashSet(Arrays.asList(collection)); + return set.size() == collection.length; + } + + /** + * Returns true if the union of the given collections of properties and + * references have unique Java types + */ + private boolean calcPropRefUniqueness(Collection props, Collection refs) { + + Class[] classes = new Class[props.size() + refs.size()]; + int i = 0; + for (JavaElementImpl property : props) { + classes[i] = property.getType(); + i++; + } + for (JavaElementImpl reference : refs) { + classes[i] = reference.getType(); + i++; + } + return areUnique(classes); + } + + /** + * Unambiguously finds the reference or property associated with the given + * type + * + * @return the name of the reference or property if found, null if not + * @throws AmbiguousConstructorException if the constructor parameter cannot + * be resolved to a property or reference + */ + private boolean findReferenceOrProperty(JavaParameterImpl parameter, + Map props, + Map refs) throws AmbiguousConstructorException { + + boolean found = false; + if (!"".equals(parameter.getName())) { + // Match by name + JavaElementImpl prop = props.get(parameter.getName()); + if (prop != null && prop.getType() == parameter.getType()) { + parameter.setClassifer(Property.class); + return true; + } + JavaElementImpl ref = refs.get(parameter.getName()); + if (ref != null && ref.getType() == parameter.getType()) { + parameter.setClassifer(Reference.class); + return true; + } + } + for (JavaElementImpl property : props.values()) { + if (property.getType() == parameter.getType()) { + if (found) { + throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type", + (Member)parameter.getAnchor()); + } + parameter.setClassifer(Property.class); + parameter.setName(property.getName()); + found = true; + // do not break since ambiguities must be checked, i.e. more + // than one prop or ref of the same type + } + } + for (JavaElementImpl reference : refs.values()) { + if (reference.getType() == parameter.getType()) { + if (found) { + throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type", + (Member)parameter.getAnchor()); + } + parameter.setClassifer(Reference.class); + parameter.setName(reference.getName()); + found = true; + // do not break since ambiguities must be checked, i.e. more + // than one prop or ref of the same type + } + } + return found; + } + + /** + * Returns true if a given type is reference according to the SCA + * specification rules for determining reference types The following rules + * are used to determine whether an unannotated field or setter method is a + * property or reference: + *

    + *
  1. If its type is simple, then it is a property. + *
  2. If its type is complex, then if the type is an interface marked by + * + * @Remotable, then it is a reference; otherwise, it is a property. + *
  3. Otherwise, if the type associated with the member is an + * array or a java.util.Collection, the basetype is the element + * type of the array or the parameterized type of the + * Collection; otherwise the basetype is the member type. If the + * basetype is an interface with an + * @Remotable or + * @Service annotation then the member is defined as a reference. Otherwise, + * it is defined as a property. + *
+ *

+ * The name of the reference or of the property is derived from the + * name found on the setter method or on the field. + */ + private boolean isReferenceType(Class cls, Type genericType) { + Class baseType = JavaIntrospectionHelper.getBaseType(cls, genericType); + return baseType.isInterface() && (baseType.isAnnotationPresent(Remotable.class) || baseType + .isAnnotationPresent(Service.class)); + } + + /** + * Returns true if the given operation is defined in the collection of + * service interfaces + */ + private boolean isInServiceInterface(Method operation, List services) { + for (org.apache.tuscany.sca.assembly.Service service : services) { + Interface interface1 = service.getInterfaceContract().getInterface(); + if (interface1 instanceof JavaInterface) { + Class clazz = ((JavaInterface)interface1).getJavaClass(); + if (isMethodMatched(clazz, operation)) { + return true; + } + } + } + return false; + } + + /** + * Test if the class declares a method which matches the signature of the + * given method + * + * @param clazz + * @param method + * @return + */ + private boolean isMethodMatched(Class clazz, Method method) { + if (method.getDeclaringClass() == clazz) { + return true; + } + Method[] methods = clazz.getMethods(); + for (Method m : methods) { + if (JavaIntrospectionHelper.exactMethodMatch(method, m)) { + return true; + } + } + return false; + } + + /** + * Creates a mapped property + * + * @param name the property name + * @param member the injection site the reference maps to + * @param paramType the property type + */ + private org.apache.tuscany.sca.assembly.Property createProperty(String name, Class paramType) { + org.apache.tuscany.sca.assembly.Property property = assemblyFactory.createProperty(); + property.setName(name); + property.setXSDType(JavaXMLMapper.getXMLType(paramType)); + return property; + } + + private boolean isAnnotated(JavaParameterImpl parameter) { + for (Annotation annotation : parameter.getAnnotations()) { + Class annotType = annotation.annotationType(); + if (annotType.equals(Property.class) || annotType.equals(Reference.class) + || annotType.equals(Resource.class)) { + return true; + } + } + return false; + } + + public boolean areUnique(JavaParameterImpl[] parameters) { + Set set = new HashSet(parameters.length); + for (JavaParameterImpl p : parameters) { + if (!set.add(p.getType())) { + return false; + } + } + return true; + } + + public org.apache.tuscany.sca.assembly.Reference createReference(String name, Class paramType) + throws IntrospectionException { + org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference(); + reference.setName(name); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + reference.setInterfaceContract(interfaceContract); + try { + JavaInterface callInterface = javaFactory.createJavaInterface(paramType); + reference.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + reference.getInterfaceContract().setCallbackInterface(callbackInterface); + } + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } catch (InvalidInterfaceException e1) { + throw new IntrospectionException(e1); + } + try { + processCallback(paramType, reference); + } catch (InvalidServiceType e) { + throw new IntrospectionException(e); + } + return reference; + } + + public org.apache.tuscany.sca.assembly.Service createService(Class interfaze) throws InvalidInterfaceException { + org.apache.tuscany.sca.assembly.Service service = assemblyFactory.createService(); + service.setName(interfaze.getSimpleName()); + + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + service.setInterfaceContract(interfaceContract); + + JavaInterface callInterface = javaFactory.createJavaInterface(interfaze); + service.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + service.getInterfaceContract().setCallbackInterface(callbackInterface); + } + + Interface javaInterface = service.getInterfaceContract().getInterface(); + javaInterface.setRemotable(interfaze.getAnnotation(Remotable.class) != null); + service.getInterfaceContract().setInterface(javaInterface); + return service; + } + + public void processCallback(Class interfaze, Contract contract) throws InvalidServiceType { + Callback callback = interfaze.getAnnotation(Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + Class callbackClass = callback.value(); + JavaInterface javaInterface = javaFactory.createJavaInterface(); + javaInterface.setJavaClass(callbackClass); + contract.getInterfaceContract().setCallbackInterface(javaInterface); + } else if (callback != null && Void.class.equals(callback.value())) { + throw new InvalidServiceType("No callback interface specified on annotation", interfaze); + } + } + + public boolean injectionAnnotationsPresent(Annotation[][] annots) { + for (Annotation[] annotations : annots) { + for (Annotation annotation : annotations) { + Class annotType = annotation.annotationType(); + if (annotType.equals(Property.class) || annotType.equals(Reference.class) + || annotType.equals(Resource.class)) { + return true; + } + } + } + return false; + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.java new file mode 100644 index 0000000000..f0e0f65587 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalCallbackReferenceException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal use of {@link org.osoa.sca.annotations.Callback} on a reference + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public class IllegalCallbackReferenceException extends IntrospectionException { + private static final long serialVersionUID = -8932525723147700591L; + + public IllegalCallbackReferenceException(String message) { + super(message); + } + + public IllegalCallbackReferenceException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.java new file mode 100644 index 0000000000..14124f0b31 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalContextException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Context} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalContextException extends IntrospectionException { + private static final long serialVersionUID = -6946383136750117008L; + + public IllegalContextException(String message) { + super(message); + } + + public IllegalContextException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.java new file mode 100644 index 0000000000..f85cc40248 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalDestructorException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Destroy} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalDestructorException extends IntrospectionException { + private static final long serialVersionUID = 365719353107446326L; + + public IllegalDestructorException(String message) { + super(message); + } + + public IllegalDestructorException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.java new file mode 100644 index 0000000000..010713d14f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalInitException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal signature for a method decorated with {@link @org.osoa.sca.annotations.Init} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalInitException extends IntrospectionException { + private static final long serialVersionUID = -3690763271986854701L; + + public IllegalInitException(String message) { + super(message); + } + + public IllegalInitException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalPropertyException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalPropertyException.java new file mode 100644 index 0000000000..21ebd433a7 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalPropertyException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal property definition in a component type + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalPropertyException extends IntrospectionException { + private static final long serialVersionUID = -2836849110706758494L; + + public IllegalPropertyException(String message) { + super(message); + } + + public IllegalPropertyException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.java new file mode 100644 index 0000000000..8a50d978e3 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalReferenceException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal reference definition in a component type + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalReferenceException extends IntrospectionException { + private static final long serialVersionUID = 4612984122225271395L; + + public IllegalReferenceException(String message) { + super(message); + } + + public IllegalReferenceException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.java new file mode 100644 index 0000000000..9c96567844 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalResourceException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal resource definition in a component type + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalResourceException extends IntrospectionException { + private static final long serialVersionUID = -1100936539412435579L; + + public IllegalResourceException(String message) { + super(message); + } + + public IllegalResourceException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.java new file mode 100644 index 0000000000..4281cfe358 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/IllegalServiceDefinitionException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an illegal use of the {@link @org.osoa.sca.annotations.Service} annotation + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class IllegalServiceDefinitionException extends IntrospectionException { + private static final long serialVersionUID = -7151534258405092548L; + + public IllegalServiceDefinitionException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java new file mode 100644 index 0000000000..94ceb2d3a5 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.osoa.sca.annotations.Init; + +/** + * Processes the {@link @Init} annotation on a component implementation and + * updates the component type with the decorated initializer method + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class InitProcessor extends BaseJavaClassVisitor { + + public InitProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + Init annotation = method.getAnnotation(Init.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 0) { + throw new IllegalInitException("Initializer must not have argments", method); + } + if (type.getInitMethod() != null) { + throw new DuplicateInitException("More than one initializer found on implementaton"); + } + if (Modifier.isProtected(method.getModifiers())) { + method.setAccessible(true); + } + type.setInitMethod(method); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.java new file mode 100644 index 0000000000..ec3c2c4bb6 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConstructorException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an invalid constructor definition, e.g. when the number of injection names specified in {@link + * org.osoa.sca.annotations.Constructor} do not match the number of actual constructor parameters + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class InvalidConstructorException extends IntrospectionException { + private static final long serialVersionUID = 1411492435210741512L; + + public InvalidConstructorException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java new file mode 100644 index 0000000000..bb460e2840 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidConversationalImplementation.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Raised when an implementation specifies improper conversational metadata + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class InvalidConversationalImplementation extends IntrospectionException { + private static final long serialVersionUID = -5487291552769408149L; + + public InvalidConversationalImplementation(String message) { + super(message); + } + + public InvalidConversationalImplementation(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.java new file mode 100644 index 0000000000..11100cf45e --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidPropertyException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an invalid usage of {@link org.osoa.sca.annotations.Property} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class InvalidPropertyException extends IntrospectionException { + private static final long serialVersionUID = -2682862652069727948L; + + public InvalidPropertyException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java new file mode 100644 index 0000000000..e416f09f85 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidReferenceException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an invalid usage of {@link org.osoa.sca.annotations.Reference} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class InvalidReferenceException extends IntrospectionException { + private static final long serialVersionUID = -3285246635989254165L; + + public InvalidReferenceException(String message) { + super(message); + } + + public InvalidReferenceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidReferenceException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.java new file mode 100644 index 0000000000..b1168a586a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidResourceException.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.implementation.java.introspect.impl; + +import java.lang.reflect.Member; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Denotes an invalid usage of {@link @org.apache.tuscany.api.annotation.Resource} + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class InvalidResourceException extends IntrospectionException { + private static final long serialVersionUID = 511728001735534934L; + + public InvalidResourceException(String message) { + super(message); + } + + public InvalidResourceException(String message, Member member) { + super(message, member); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.java new file mode 100644 index 0000000000..736bc6e691 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InvalidServiceType.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when a service type specified by an {@link org.osoa.sca.annotations.Service} annotation is invalid, e.g. it is + * not an interface + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class InvalidServiceType extends IntrospectionException { + private static final long serialVersionUID = -1076466639416644386L; + private Class serviceType; + + public InvalidServiceType(String message) { + super(message); + } + + public InvalidServiceType(String message, Class clazz) { + super(message); + this.serviceType = clazz; + } + + /** + * @return the serviceType + */ + public Class getServiceType() { + return serviceType; + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java new file mode 100644 index 0000000000..d800450453 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaIntrospectionHelper.java @@ -0,0 +1,555 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.beans.Introspector; +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.security.AccessController; +import java.security.PrivilegedAction; +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.logging.Logger; + +import org.osoa.sca.CallableReference; + +/** + * Implements various reflection-related operations + * + * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $ + */ +public final class JavaIntrospectionHelper { + private static final Logger logger = Logger.getLogger(JavaIntrospectionHelper.class.getName()); + private static final Class[] EMPTY_CLASS_ARRY = new Class[0]; + + /** + * Hide the constructor + */ + private JavaIntrospectionHelper() { + } + + /** + * Returns a collection of public, and protected fields declared by a class + * or one of its supertypes + */ + public static Set getAllPublicAndProtectedFields(Class clazz, boolean validating) { + return getAllPublicAndProtectedFields(clazz, new HashSet(), validating); + } + + private static void checkInvalidAnnotations(AnnotatedElement element) { + for (Annotation a : element.getAnnotations()) { + if ("org.osoa.sca.annotations".equals(a.annotationType().getPackage().getName())) { + logger.warning("Invalid annotation " + a + " is found on " + element); + } + } + } + + /** + * Recursively evaluates the type hierarchy to return all fields that are + * public or protected + */ + private static Set getAllPublicAndProtectedFields(Class clazz, Set fields, boolean validating) { + if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) { + return fields; + } + fields = getAllPublicAndProtectedFields(clazz.getSuperclass(), fields, validating); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { + int modifiers = field.getModifiers(); + if ((Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) && !Modifier.isStatic(modifiers)) { + field.setAccessible(true); // ignore Java accessibility + fields.add(field); + } else { + if (validating) { + checkInvalidAnnotations(field); + } + } + } + return fields; + } + + /** + * Returns a collection of public and protected methods declared by a class + * or one of its supertypes. Note that overridden methods will not be + * returned in the collection (i.e. only the method override will be).

+ * This method can potentially be expensive as reflection information is not + * cached. It is assumed that this method will be used during a + * configuration phase. + */ + public static Set getAllUniquePublicProtectedMethods(Class clazz, boolean validating) { + return getAllUniqueMethods(clazz, new HashSet(), validating); + } + + /** + * Recursively evaluates the type hierarchy to return all unique methods + */ + private static Set getAllUniqueMethods(Class pClass, Set methods, boolean validating) { + if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) { + return methods; + } + // we first evaluate methods of the subclass and then move to the parent + Method[] declaredMethods = pClass.getDeclaredMethods(); + for (final Method declaredMethod : declaredMethods) { + int modifiers = declaredMethod.getModifiers(); + if ((!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers)) || Modifier.isStatic(modifiers)) { + if (validating) { + checkInvalidAnnotations(declaredMethod); + } + continue; + } + if (methods.size() == 0) { + methods.add(declaredMethod); + } else { + List temp = new ArrayList(); + boolean matched = false; + for (Method method : methods) { + // only add if not already in the set from a superclass (i.e. + // the method is not overridden) + if (exactMethodMatch(declaredMethod, method)) { + matched = true; + break; + } + } + if (!matched) { + // Allow privileged access to set accessibility. Requires ReflectPermission + // in security policy. + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + declaredMethod.setAccessible(true); + return null; + } + }); + temp.add(declaredMethod); + } + methods.addAll(temp); + temp.clear(); + } + } + // evaluate class hierarchy - this is done last to track inherited + // methods + methods = getAllUniqueMethods(pClass.getSuperclass(), methods, validating); + return methods; + } + + /** + * Finds the closest matching field with the given name, that is, a field of + * the exact specified type or, alternately, of a supertype. + * + * @param name the name of the field + * @param type the field type + * @param fields the collection of fields to search + * @return the matching field or null if not found + */ + public static Field findClosestMatchingField(String name, Class type, Set fields) { + Field candidate = null; + for (Field field : fields) { + if (field.getName().equals(name)) { + if (field.getType().equals(type)) { + return field; // exact match + } else if (field.getType().isAssignableFrom(type) || (field.getType().isPrimitive() && primitiveAssignable(field + .getType(), + type))) { + // We could have the situation where a field parameter is a + // primitive and the demarshalled value is + // an object counterpart (e.g. Integer and int) + // @spec issue + // either an interface or super class, so keep a reference + // until + // we know there are no closer types + candidate = field; + } + } + } + if (candidate != null) { + return candidate; + } else { + return null; + } + } + + /** + * Finds the closest matching method with the given name, that is, a method + * taking the exact parameter types or, alternately, parameter supertypes. + * + * @param name the name of the method + * @param types the method parameter types + * @param methods the collection of methods to search + * @return the matching method or null if not found + */ + public static Method findClosestMatchingMethod(String name, Class[] types, Set methods) { + if (types == null) { + types = EMPTY_CLASS_ARRY; + } + Method candidate = null; + for (Method method : methods) { + if (method.getName().equals(name) && method.getParameterTypes().length == types.length) { + Class[] params = method.getParameterTypes(); + boolean disqualify = false; + boolean exactMatch = true; + for (int i = 0; i < params.length; i++) { + if (!params[i].equals(types[i]) && !params[i].isAssignableFrom(types[i])) { + // no match + disqualify = true; + exactMatch = false; + break; + } else if (!params[i].equals(types[i]) && params[i].isAssignableFrom(types[i])) { + // not exact match + exactMatch = false; + } + } + if (disqualify) { + continue; + } else if (exactMatch) { + return method; + } else { + candidate = method; + } + } + } + if (candidate != null) { + return candidate; + } else { + return null; + } + } + + /** + * Determines if two methods "match" - that is, they have the same method + * names and exact parameter types (one is not a supertype of the other) + */ + public static boolean exactMethodMatch(Method method1, Method method2) { + if (!method1.getName().equals(method2.getName())) { + return false; + } + Class[] types1 = method1.getParameterTypes(); + Class[] types2 = method2.getParameterTypes(); + if (types1.length != types2.length) { + return false; + } + boolean matched = true; + for (int i = 0; i < types1.length; i++) { + if (types1[i] != types2[i]) { + matched = false; + break; + } + } + return matched; + } + + public static Constructor getDefaultConstructor(Class clazz) throws NoSuchMethodException { + return clazz.getConstructor((Class[])null); + } + + /** + * Returns the simple name of a class - i.e. the class name devoid of its + * package qualifier + * + * @param implClass the implementation class + */ + public static String getBaseName(Class implClass) { + return implClass.getSimpleName(); + } + + public static boolean isImmutable(Class clazz) { + return String.class == clazz || clazz.isPrimitive() + || Number.class.isAssignableFrom(clazz) + || Boolean.class.isAssignableFrom(clazz) + || Character.class.isAssignableFrom(clazz) + || Byte.class.isAssignableFrom(clazz); + } + + /** + * Takes a property name and converts it to a getter method name according + * to JavaBean conventions. For example, property + * foo is returned as getFoo + */ + public static String toGetter(String name) { + return "get" + name.toUpperCase().substring(0, 1) + name.substring(1); + } + + /** + * Takes a setter or getter method name and converts it to a property name + * according to JavaBean conventions. For example, setFoo(var) + * is returned as property foo + */ + public static String toPropertyName(String name) { + if (!name.startsWith("set")) { + return name; + } + + if (name == null || name.length() == 0) { + return name; + } + if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && + Character.isUpperCase(name.charAt(0))){ + return name; + } + char chars[] = name.toCharArray(); + chars[0] = Character.toLowerCase(chars[0]); + return new String(chars); + + } + + public static Class getErasure(Type type) { + if (type instanceof Class) { + return (Class)type; + } else if (type instanceof GenericArrayType) { + // FIXME: How to deal with the []? + GenericArrayType arrayType = (GenericArrayType)type; + return getErasure(arrayType.getGenericComponentType()); + } else if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType)type; + return getErasure(pType.getRawType()); + } else if (type instanceof WildcardType) { + WildcardType wType = (WildcardType)type; + Type[] types = wType.getUpperBounds(); + return getErasure(types[0]); + } else if (type instanceof TypeVariable) { + TypeVariable var = (TypeVariable)type; + Type[] types = var.getBounds(); + return getErasure(types[0]); + } + return null; + } + + public static Class getBaseType(Class cls, Type genericType) { + if (cls.isArray()) { + return cls.getComponentType(); + } else if (Collection.class.isAssignableFrom(cls)) { + if (genericType instanceof ParameterizedType) { + // Collection + ParameterizedType parameterizedType = (ParameterizedType)genericType; + Type baseType = parameterizedType.getActualTypeArguments()[0]; + if (baseType instanceof GenericArrayType) { + // Base is array + return cls; + } else { + return getErasure(baseType); + } + } else { + return cls; + } + } else { + return cls; + } + } + + public static Type getParameterType(Type type) { + if (type instanceof ParameterizedType) { + // Collection + ParameterizedType parameterizedType = (ParameterizedType)type; + Type baseType = parameterizedType.getActualTypeArguments()[0]; + return baseType; + } else { + return Object.class; + } + } + + public static Class getBusinessInterface(Class cls, Type callableReferenceType) { + if (CallableReference.class.isAssignableFrom(cls) && callableReferenceType instanceof ParameterizedType) { + // Collection + ParameterizedType parameterizedType = (ParameterizedType)callableReferenceType; + Type baseType = parameterizedType.getActualTypeArguments()[0]; + if (baseType instanceof GenericArrayType) { + // Base is array + return cls; + } else { + return getErasure(baseType); + } + } + return Object.class; + } + + /** + * Takes a property name and converts it to a setter method name according + * to JavaBean conventions. For example, the property + * foo is returned as setFoo(var) + */ + public static String toSetter(String name) { + return "set" + name.toUpperCase().substring(0, 1) + name.substring(1); + } + + /** + * Compares a two types, assuming one is a primitive, to determine if the + * other is its object counterpart + */ + private static boolean primitiveAssignable(Class memberType, Class param) { + if (memberType == Integer.class) { + return param == Integer.TYPE; + } else if (memberType == Double.class) { + return param == Double.TYPE; + } else if (memberType == Float.class) { + return param == Float.TYPE; + } else if (memberType == Short.class) { + return param == Short.TYPE; + } else if (memberType == Character.class) { + return param == Character.TYPE; + } else if (memberType == Boolean.class) { + return param == Boolean.TYPE; + } else if (memberType == Byte.class) { + return param == Byte.TYPE; + } else if (param == Integer.class) { + return memberType == Integer.TYPE; + } else if (param == Double.class) { + return memberType == Double.TYPE; + } else if (param == Float.class) { + return memberType == Float.TYPE; + } else if (param == Short.class) { + return memberType == Short.TYPE; + } else if (param == Character.class) { + return memberType == Character.TYPE; + } else if (param == Boolean.class) { + return memberType == Boolean.TYPE; + } else if (param == Byte.class) { + return memberType == Byte.TYPE; + } else { + return false; + } + } + + /** + * Returns the generic types represented in the given type. Usage as + * follows: + * JavaIntrospectionHelper.getGenerics(field.getGenericType()); + *

+ * JavaIntrospectionHelper.getGenerics(m.getGenericParameterTypes()[0];); + * + * @return the generic types in order of declaration or an empty array if + * the type is not genericized + */ + public static List getGenerics(Type genericType) { + List classes = new ArrayList(); + if (genericType instanceof ParameterizedType) { + ParameterizedType ptype = (ParameterizedType)genericType; + // get the type arguments + Type[] targs = ptype.getActualTypeArguments(); + for (Type targ : targs) { + classes.add(targ); + } + } + return classes; + } + + /** + * Returns the generic type specified by the class at the given position as + * in:

public class Foo{ //.. } + *

+ * JavaIntrospectionHelper.introspectGeneric(Foo.class,1); + *

+ * will return Baz. + */ + public static Class introspectGeneric(Class clazz, int pos) { + assert clazz != null : "No class specified"; + Type type = clazz.getGenericSuperclass(); + if (type instanceof ParameterizedType) { + Type[] args = ((ParameterizedType)type).getActualTypeArguments(); + if (args.length <= pos) { + throw new IllegalArgumentException("Invalid index value for generic class " + clazz.getName()); + } + return (Class)((ParameterizedType)type).getActualTypeArguments()[pos]; + } else { + Type[] interfaces = clazz.getGenericInterfaces(); + for (Type itype : interfaces) { + if (!(itype instanceof ParameterizedType)) { + continue; + } + ParameterizedType interfaceType = (ParameterizedType)itype; + return (Class)interfaceType.getActualTypeArguments()[0]; + } + } + return null; + } + + /** + * Returns the set of interfaces implemented by the given class and its + * ancestors or a blank set if none + */ + public static Set getAllInterfaces(Class clazz) { + Set implemented = new HashSet(); + getAllInterfaces(clazz, implemented); + return implemented; + } + + private static void getAllInterfaces(Class clazz, Set implemented) { + Class[] interfaces = clazz.getInterfaces(); + for (Class interfaze : interfaces) { + implemented.add(interfaze); + } + Class superClass = clazz.getSuperclass(); + // Object has no superclass so check for null + if (superClass != null && !superClass.equals(Object.class)) { + getAllInterfaces(superClass, implemented); + } + } + + public static boolean isSetter(Method method) { + return (void.class == method.getReturnType() && method.getParameterTypes().length == 1 && method.getName() + .startsWith("set")); + } + + public static boolean isGetter(Method method) { + return (void.class != method.getReturnType() && method.getParameterTypes().length == 0 && method.getName() + .startsWith("get")); + } + + private final static Map signatures = new HashMap(); + static { + signatures.put(boolean.class, "Z"); + signatures.put(byte.class, "B"); + signatures.put(char.class, "C"); + signatures.put(short.class, "S"); + signatures.put(int.class, "I"); + signatures.put(long.class, "J"); + signatures.put(float.class, "F"); + signatures.put(double.class, "D"); + }; + + public static String getSignature(Class cls) { + if (cls.isPrimitive()) { + return signatures.get(cls); + } + if (cls.isArray()) { + return "[" + getSignature(cls.getComponentType()); + } + return "L" + cls.getName().replace('.', '/') + ";"; + } + + public static Class getArrayType(Class componentType, int dims) throws ClassNotFoundException { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < dims; i++) { + buf.append('['); + } + buf.append(getSignature(componentType)); + return Class.forName(buf.toString(), false, componentType.getClassLoader()); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java new file mode 100644 index 0000000000..a54c418af8 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/NoConstructorException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when a suitable constructor for a component implementation cannot be found + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class NoConstructorException extends IntrospectionException { + private static final long serialVersionUID = 3086706387280694424L; + + public NoConstructorException() { + } + + public NoConstructorException(String message) { + super(message); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java new file mode 100644 index 0000000000..d7a8746c05 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessor.java @@ -0,0 +1,292 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Callback; +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.osoa.sca.annotations.PolicySets; +import org.osoa.sca.annotations.Requires; + +/** + * Processes an {@link org.osoa.sca.annotations.Requires} annotation + * + * @version $Rev: + */ +public class PolicyProcessor extends BaseJavaClassVisitor { + + private PolicyFactory policyFactory; + + public PolicyProcessor(AssemblyFactory assemblyFactory, PolicyFactory policyFactory) { + super(assemblyFactory); + this.policyFactory = policyFactory; + } + + private QName getQName(String intentName) { + QName qname; + if (intentName.startsWith("{")) { + int i = intentName.indexOf('}'); + if (i != -1) { + qname = new QName(intentName.substring(1, i), intentName.substring(i + 1)); + } else { + qname = new QName("", intentName); + } + } else { + qname = new QName("", intentName); + } + return qname; + } + + /** + * Read policy intents on the given interface or class + * @param clazz + * @param requiredIntents + */ + private void readIntentsAndPolicySets(Class clazz, + List requiredIntents, + List policySets) { + Requires intentAnnotation = clazz.getAnnotation(Requires.class); + if (intentAnnotation != null) { + String[] intentNames = intentAnnotation.value(); + if (intentNames.length != 0) { + for (String intentName : intentNames) { + + // Add each intent to the list + Intent intent = policyFactory.createIntent(); + intent.setName(getQName(intentName)); + requiredIntents.add(intent); + } + } + } + + PolicySets policySetAnnotation = clazz.getAnnotation(PolicySets.class); + if (policySetAnnotation != null) { + String[] policySetNames = policySetAnnotation.value(); + if (policySetNames.length != 0) { + for (String policySetName : policySetNames) { + + // Add each intent to the list + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(getQName(policySetName)); + policySets.add(policySet); + } + } + } + } + + private void readIntents(Requires intentAnnotation, List requiredIntents) { + //Requires intentAnnotation = method.getAnnotation(Requires.class); + if (intentAnnotation != null) { + String[] intentNames = intentAnnotation.value(); + if (intentNames.length != 0) { + //Operation operation = assemblyFactory.createOperation(); + //operation.setName(method.getName()); + //operation.setUnresolved(true); + for (String intentName : intentNames) { + + // Add each intent to the list, associated with the + // operation corresponding to the annotated method + Intent intent = policyFactory.createIntent(); + intent.setName(getQName(intentName)); + //intent.getOperations().add(operation); + requiredIntents.add(intent); + } + } + } + } + + private void readPolicySets(PolicySets policySetAnnotation, List policySets) { + if (policySetAnnotation != null) { + String[] policySetNames = policySetAnnotation.value(); + if (policySetNames.length != 0) { + //Operation operation = assemblyFactory.createOperation(); + //operation.setName(method.getName()); + //operation.setUnresolved(true); + for (String policySetName : policySetNames) { + // Add each intent to the list, associated with the + // operation corresponding to the annotated method + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(getQName(policySetName)); + //intent.getOperations().add(operation); + policySets.add(policySet); + } + } + } + } + + @Override + public void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + + // Read intents on the Java implementation class + if ( type instanceof PolicySetAttachPoint ) { + readIntentsAndPolicySets(clazz, + ((PolicySetAttachPoint)type).getRequiredIntents(), + ((PolicySetAttachPoint)type).getPolicySets()); + } + + // Process annotations on the service interfaces + //TODO This will have to move to a JavaInterface introspector later + for (Service service: type.getServices()) { + InterfaceContract interfaceContract = service.getInterfaceContract(); + if (interfaceContract instanceof JavaInterfaceContract) { + JavaInterfaceContract javaInterfaceContract = (JavaInterfaceContract)interfaceContract; + + // Read intents on the service interface + if (javaInterfaceContract.getInterface() != null) { + JavaInterface javaInterface = (JavaInterface)javaInterfaceContract.getInterface(); + if (javaInterface.getJavaClass() != null) { + readIntentsAndPolicySets(javaInterface.getJavaClass(), + service.getRequiredIntents(), + service.getPolicySets()); + + // Read intents on the service interface methods + Method[] methods = javaInterface.getJavaClass().getMethods(); + ConfiguredOperation confOp = null; + for (Method method: methods) { + if ( method.getAnnotation(Requires.class) != null || + method.getAnnotation(PolicySets.class) != null ) { + confOp = assemblyFactory.createConfiguredOperation(); + confOp.setName(method.getName()); + confOp.setContractName(service.getName()); + + service.getConfiguredOperations().add(confOp); + readIntents(method.getAnnotation(Requires.class), confOp.getRequiredIntents()); + readPolicySets(method.getAnnotation(PolicySets.class), confOp.getPolicySets()); + } + } + } + + } + + // Read intents on the callback interface + if (javaInterfaceContract.getCallbackInterface() != null) { + JavaInterface javaCallbackInterface = (JavaInterface)javaInterfaceContract.getCallbackInterface(); + if (javaCallbackInterface.getJavaClass() != null) { + Callback callback = service.getCallback(); + if (callback == null) { + callback = assemblyFactory.createCallback(); + service.setCallback(callback); + } + readIntentsAndPolicySets(javaCallbackInterface.getJavaClass(), + callback.getRequiredIntents(), + callback.getPolicySets()); + + // Read intents on the callback interface methods + Method[] methods = javaCallbackInterface.getJavaClass().getMethods(); + ConfiguredOperation confOp = null; + for (Method method: methods) { + confOp = assemblyFactory.createConfiguredOperation(); + confOp.setName(method.getName()); + callback.getConfiguredOperations().add(confOp); + readIntents(method.getAnnotation(Requires.class), confOp.getRequiredIntents()); + readPolicySets(method.getAnnotation(PolicySets.class), confOp.getPolicySets()); + } + } + } + } + } + } + + private Reference getReference(Method method, JavaImplementation type) { + //since the ReferenceProcessor is called ahead of the PolicyProcessor the type should have + //picked up the reference setter method + org.osoa.sca.annotations.Reference annotation = + method.getAnnotation(org.osoa.sca.annotations.Reference.class); + if (annotation != null) { + if (JavaIntrospectionHelper.isSetter(method)) { + String name = annotation.name(); + if ("".equals(name)) { + name = JavaIntrospectionHelper.toPropertyName(method.getName()); + } + return getReferenceByName(name, type); + } + } + return null; + } + + private Reference getReferenceByName(String name, JavaImplementation type) { + for ( Reference reference : type.getReferences() ) { + if ( reference.getName().equals(name) ) { + return reference; + } + } + return null; + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + org.osoa.sca.annotations.Reference annotation = + field.getAnnotation( org.osoa.sca.annotations.Reference.class); + if (annotation == null) { + return; + } + String name = annotation.name(); + if ("".equals(name)) { + name = field.getName(); + } + + Reference reference = null; + if ( (reference = getReferenceByName(name, type)) != null ) { + readIntents(field.getAnnotation(Requires.class), reference.getRequiredIntents()); + readPolicySets(field.getAnnotation(PolicySets.class), reference.getPolicySets()); + } + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + Reference reference = null; + if ( (reference = getReference(method, type)) != null ) { + readIntents(method.getAnnotation(Requires.class), reference.getRequiredIntents()); + readPolicySets(method.getAnnotation(PolicySets.class), reference.getPolicySets()); + } else { + if ( type instanceof OperationsConfigurator ) { + //Read the intents specified on the given implementation method + if ( (method.getAnnotation(Requires.class) != null || + method.getAnnotation(PolicySets.class) != null ) && + (type instanceof PolicySetAttachPoint )) { + ConfiguredOperation confOp = assemblyFactory.createConfiguredOperation(); + confOp.setName(method.getName()); + ((OperationsConfigurator)type).getConfiguredOperations().add(confOp); + + + readIntents(method.getAnnotation(Requires.class), confOp.getRequiredIntents()); + readPolicySets(method.getAnnotation(PolicySets.class), confOp.getPolicySets()); + } + } + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java new file mode 100644 index 0000000000..c96240c82b --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessor.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.osoa.sca.annotations.Property; + +/** + * Processes an {@link @Property} annotation, updating the component type with + * corresponding {@link JavaMappedProperty} + * + * @version $Rev: 584985 $ $Date: 2007-10-15 17:47:36 -0700 (Mon, 15 Oct 2007) $ + */ +public class PropertyProcessor extends AbstractPropertyProcessor { + + public PropertyProcessor(AssemblyFactory assemblyFactory) { + super(assemblyFactory, Property.class); + } + + @Override + protected String getName(Property annotation) { + return annotation.name(); + } + + @Override + protected void initProperty(org.apache.tuscany.sca.assembly.Property property, Property annotation) { + property.setMustSupply(annotation.required()); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.java new file mode 100644 index 0000000000..c801c92092 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessor.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.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getBaseType; + +import java.lang.annotation.ElementType; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.CallableReference; +import org.osoa.sca.annotations.Reference; + +/** + * Processes an {@link @Reference} annotation, updating the component type with + * corresponding {@link + * org.apache.tuscany.spi.implementation.java.JavaMappedReference} + * + * @version $Rev: 584985 $ $Date: 2007-10-15 17:47:36 -0700 (Mon, 15 Oct 2007) $ + */ +public class ReferenceProcessor extends BaseJavaClassVisitor { + private JavaInterfaceFactory javaFactory; + + public ReferenceProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory) { + super(assemblyFactory); + this.javaFactory = javaFactory; + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + Reference annotation = method.getAnnotation(Reference.class); + if (annotation == null) { + return; // Not a reference annotation. + } + if (!JavaIntrospectionHelper.isSetter(method)) { + throw new IllegalReferenceException("Annotated method is not a setter: " + method, method); + } + String name = annotation.name(); + if ("".equals(name)) { + name = JavaIntrospectionHelper.toPropertyName(method.getName()); + } + JavaElementImpl ref = type.getReferenceMembers().get(name); + // Setter override field + if (ref != null && ref.getElementType() != ElementType.FIELD) { + throw new DuplicateReferenceException(name); + } + removeReference(ref, type); + + JavaElementImpl element = new JavaElementImpl(method, 0); + org.apache.tuscany.sca.assembly.Reference reference = createReference(element, name); + type.getReferences().add(reference); + type.getReferenceMembers().put(name, element); + } + + private boolean removeReference(JavaElementImpl ref, JavaImplementation type) { + if (ref == null) { + return false; + } + List refs = type.getReferences(); + for (int i = 0; i < refs.size(); i++) { + if (refs.get(i).getName().equals(ref.getName())) { + refs.remove(i); + return true; + } + } + return false; + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + Reference annotation = field.getAnnotation(Reference.class); + if (annotation == null) { + return; + } + String name = annotation.name(); + if ("".equals(name)) { + name = field.getName(); + } + JavaElementImpl ref = type.getReferenceMembers().get(name); + if (ref != null && ref.getElementType() == ElementType.FIELD) { + throw new DuplicateReferenceException(name); + } + + // Setter method override field + if (ref == null) { + JavaElementImpl element = new JavaElementImpl(field); + org.apache.tuscany.sca.assembly.Reference reference = createReference(element, name); + type.getReferences().add(reference); + type.getReferenceMembers().put(name, element); + } + } + + @Override + public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) + throws IntrospectionException { + Reference refAnnotation = parameter.getAnnotation(Reference.class); + if (refAnnotation == null) { + return; + } + String paramName = parameter.getName(); + String name = getReferenceName(paramName, parameter.getIndex(), refAnnotation.name()); + JavaElementImpl ref = type.getReferenceMembers().get(name); + + // Setter override field + if (ref != null && ref.getElementType() != ElementType.FIELD) { + throw new DuplicateReferenceException(name); + } + + removeReference(ref, type); + org.apache.tuscany.sca.assembly.Reference reference = createReference(parameter, name); + type.getReferences().add(reference); + type.getReferenceMembers().put(name, parameter); + parameter.setClassifer(Reference.class); + parameter.setName(name); + } + + private String getReferenceName(String paramName, int pos, String name) throws InvalidConstructorException { + if ("".equals(name)) { + name = paramName; + } + if ("".equals(name)) { + return "_ref" + pos; + } + if (!"".equals(paramName) && !name.equals(paramName)) { + throw new InvalidConstructorException("Mismatching names specified for reference parameter " + pos); + } else { + return name; + } + } + + private org.apache.tuscany.sca.assembly.Reference createReference(JavaElementImpl element, String name) + throws IntrospectionException { + org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference(); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + reference.setInterfaceContract(interfaceContract); + + // reference.setMember((Member)element.getAnchor()); + boolean required = true; + Reference ref = element.getAnnotation(Reference.class); + if (ref != null) { + required = ref.required(); + } + // reference.setRequired(required); + reference.setName(name); + Class rawType = element.getType(); + if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_N); + } else { + reference.setMultiplicity(Multiplicity.ZERO_N); + } + } else { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_ONE); + } else { + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } + } + Type genericType = element.getGenericType(); + Class baseType = getBaseType(rawType, genericType); + if (CallableReference.class.isAssignableFrom(baseType)) { + if (Collection.class.isAssignableFrom(rawType)) { + genericType = JavaIntrospectionHelper.getParameterType(genericType); + } + baseType = JavaIntrospectionHelper.getBusinessInterface(baseType, genericType); + } + try { + JavaInterface callInterface = javaFactory.createJavaInterface(baseType); + reference.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + reference.getInterfaceContract().setCallbackInterface(callbackInterface); + } + } catch (InvalidInterfaceException e) { + throw new IntrospectionException(e); + } + return reference; + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/Resource.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/Resource.java new file mode 100644 index 0000000000..aa3c595d40 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/Resource.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to indicate a resource should be provided to an implementation by the runtime. + * + * @version $Rev: 563019 $ $Date: 2007-08-05 20:43:59 -0700 (Sun, 05 Aug 2007) $ + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Resource { + + /** + * Denotes the name of the resource declared by the implementation. + */ + String name() default ""; + + /** + * Denotes if the resource is optional + */ + boolean optional() default false; + + /** + * Denotes the default name of the resource provided by the runtime environment. + */ + String mappedName() default ""; +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java new file mode 100644 index 0000000000..a7822cf150 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessor.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; + +/** + * Processes an {@link @Resource} annotation, updating the component type with + * corresponding {@link org.apache.tuscany.spi.implementation.java.JavaResourceImpl} + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ResourceProcessor extends BaseJavaClassVisitor { + + public ResourceProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + org.apache.tuscany.sca.implementation.java.introspect.impl.Resource annotation = method + .getAnnotation(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalResourceException("Resource setter must have one parameter", method); + } + String name = annotation.name(); + if (name.length() < 1) { + name = JavaIntrospectionHelper.toPropertyName(method.getName()); + } + if (type.getResources().get(name) != null) { + throw new DuplicateResourceException(name); + } + + String mappedName = annotation.mappedName(); + JavaResourceImpl resource = createResource(name, new JavaElementImpl(method, 0)); + resource.setOptional(annotation.optional()); + if (mappedName.length() > 0) { + resource.setMappedName(mappedName); + } + type.getResources().put(resource.getName(), resource); + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + + org.apache.tuscany.sca.implementation.java.introspect.impl.Resource annotation = field + .getAnnotation(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + if (annotation == null) { + return; + } + String name = annotation.name(); + if (name.length() < 1) { + name = field.getName(); + } + if (type.getResources().get(name) != null) { + throw new DuplicateResourceException(name); + } + + String mappedName = annotation.mappedName(); + + JavaResourceImpl resource = createResource(name, new JavaElementImpl(field)); + resource.setOptional(annotation.optional()); + if (mappedName.length() > 0) { + resource.setMappedName(mappedName); + } + type.getResources().put(resource.getName(), resource); + } + + @SuppressWarnings("unchecked") + public JavaResourceImpl createResource(String name, JavaElementImpl element) { + element.setClassifer(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + element.setName(name); + return new JavaResourceImpl(element); + } + + @Override + public void visitConstructorParameter(JavaParameterImpl parameter, JavaImplementation type) + throws IntrospectionException { + org.apache.tuscany.sca.implementation.java.introspect.impl.Resource resourceAnnotation = parameter + .getAnnotation(org.apache.tuscany.sca.implementation.java.introspect.impl.Resource.class); + if (resourceAnnotation != null) { + String name = resourceAnnotation.name(); + if ("".equals(name)) { + name = parameter.getName(); + } + if ("".equals(name)) { + throw new InvalidResourceException("Missing resource name", (Member)parameter.getAnchor()); + } + + if (!"".equals(parameter.getName()) && !name.equals(parameter.getName())) { + throw new InvalidConstructorException("Mismatched resource name: " + parameter); + } + + if (type.getResources().get(name) != null) { + throw new DuplicateResourceException(name); + } + + String mappedName = resourceAnnotation.mappedName(); + + JavaResourceImpl resource = createResource(name, parameter); + resource.setOptional(resourceAnnotation.optional()); + if (mappedName.length() > 0) { + resource.setMappedName(mappedName); + } + type.getResources().put(resource.getName(), resource); + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.java new file mode 100644 index 0000000000..b2492e60fb --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessor.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl; + +/** + * Processes the {@link JavaScopeImpl} annotation and updates the component type with the corresponding implmentation scope + * + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ScopeProcessor extends BaseJavaClassVisitor { + + public ScopeProcessor(AssemblyFactory factory) { + super(factory); + } + + @Override + public void visitClass(Class clazz, + JavaImplementation type) + throws IntrospectionException { + org.osoa.sca.annotations.Scope annotation = clazz.getAnnotation(org.osoa.sca.annotations.Scope.class); + if (annotation == null) { + type.setJavaScope(JavaScopeImpl.STATELESS); + return; + } + String name = annotation.value(); + JavaScopeImpl scope; + if ("COMPOSITE".equals(name)) { + scope = JavaScopeImpl.COMPOSITE; + } else if ("SESSION".equals(name)) { + scope = JavaScopeImpl.SESSION; + } else if ("CONVERSATION".equals(name)) { + scope = JavaScopeImpl.CONVERSATION; + } else if ("REQUEST".equals(name)) { + scope = JavaScopeImpl.REQUEST; + } else { + scope = new JavaScopeImpl(name); + } + type.setJavaScope(scope); + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java new file mode 100644 index 0000000000..659f629be5 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessor.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllInterfaces; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Set; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.CallableReference; +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; + +/** + * Processes an {@link org.osoa.sca.annotations.Service} annotation and updates + * the component type with corresponding {@link Service}s. Also processes + * related {@link org.osoa.sca.annotations.Callback} annotations. + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public class ServiceProcessor extends BaseJavaClassVisitor { + private JavaInterfaceFactory javaFactory; + + public ServiceProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory) { + super(assemblyFactory); + this.javaFactory = javaFactory; + } + + @Override + public void visitClass(Class clazz, JavaImplementation type) throws IntrospectionException { + org.osoa.sca.annotations.Service annotation = clazz.getAnnotation(org.osoa.sca.annotations.Service.class); + if (annotation == null) { + // scan interfaces for remotable + Set interfaces = getAllInterfaces(clazz); + for (Class interfaze : interfaces) { + if (interfaze.isAnnotationPresent(Remotable.class) || interfaze.isAnnotationPresent(Callback.class)) { + Service service; + try { + service = createService(interfaze); + } catch (InvalidInterfaceException e) { + throw new IntrospectionException(e); + } + type.getServices().add(service); + } + } + return; + } + Class[] interfaces = annotation.interfaces(); + if (interfaces.length == 0) { + Class interfaze = annotation.value(); + if (Void.class.equals(interfaze)) { + throw new IllegalServiceDefinitionException("No interfaces specified"); + } else { + interfaces = new Class[1]; + interfaces[0] = interfaze; + } + } + for (Class interfaze : interfaces) { + try { + Service service = createService(interfaze); + type.getServices().add(service); + } catch (InvalidInterfaceException e) { + throw new IntrospectionException(e); + } + } + } + + @Override + public void visitMethod(Method method, JavaImplementation type) throws IntrospectionException { + + Callback annotation = method.getAnnotation(Callback.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalCallbackReferenceException("Setter must have one parameter", method); + } + JavaElementImpl element = new JavaElementImpl(method, 0); + createCallback(type, element); + } + + @Override + public void visitField(Field field, JavaImplementation type) throws IntrospectionException { + + Callback annotation = field.getAnnotation(Callback.class); + if (annotation == null) { + return; + } + JavaElementImpl element = new JavaElementImpl(field); + createCallback(type, element); + } + + /** + * @param type + * @param element + * @throws IllegalCallbackReferenceException + */ + private void createCallback(JavaImplementation type, JavaElementImpl element) + throws IllegalCallbackReferenceException { + Service callbackService = null; + Class callbackClass = element.getType(); + Type genericType = element.getGenericType(); + Class baseType = callbackClass; + if(CallableReference.class.isAssignableFrom(baseType)) { + // @Callback protected CallableReference callback; + // The base type will be MyCallback + baseType = JavaIntrospectionHelper.getBusinessInterface(baseType, genericType); + } + for (Service service : type.getServices()) { + JavaInterface javaInterface = (JavaInterface)service.getInterfaceContract().getCallbackInterface(); + if (javaInterface != null && baseType == javaInterface.getJavaClass()) { + callbackService = service; + } + } + if (callbackService == null) { + throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface"); + } + type.getCallbackMembers().put(baseType.getName(), element); + } + + public Service createService(Class interfaze) throws InvalidInterfaceException { + Service service = assemblyFactory.createService(); + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + service.setInterfaceContract(interfaceContract); + + // create a relative URI + service.setName(interfaze.getSimpleName()); + + JavaInterface callInterface = javaFactory.createJavaInterface(interfaze); + service.getInterfaceContract().setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass()); + service.getInterfaceContract().setCallbackInterface(callbackInterface); + } + return service; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.java new file mode 100644 index 0000000000..2c355fae72 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceTypeNotFoundException.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.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.implementation.java.IntrospectionException; + +/** + * Thrown when a service interface cannot be determined based on a heuristic evaluation of an implementation + * + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class ServiceTypeNotFoundException extends IntrospectionException { + private static final long serialVersionUID = -5124437274726947007L; + + public ServiceTypeNotFoundException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java new file mode 100644 index 0000000000..096ec970eb --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/java/org/apache/tuscany/sca/implementation/java/introspect/impl/UnknownContextTypeException.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +/** + * Thrown when a method or field marked with {@link org.osoa.sca.annotations.Context} takes an unknown type + * + * @version $Rev: 563019 $ $Date: 2007-08-05 20:43:59 -0700 (Sun, 05 Aug 2007) $ + */ +public class UnknownContextTypeException extends IllegalContextException { + private static final long serialVersionUID = 8125863714365422419L; + + public UnknownContextTypeException(String message) { + super(message); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.JavaImplementationFactory b/branches/sca-android/tuscany-implementation-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.JavaImplementationFactory new file mode 100644 index 0000000000..dc9de12632 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.JavaImplementationFactory @@ -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.implementation.java.DefaultJavaImplementationFactory diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java new file mode 100644 index 0000000000..5691c773a5 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractProcessorTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * Base class to simulate the processor sequences + * + * @version $Rev: 564364 $ $Date: 2007-08-09 13:14:52 -0700 (Thu, 09 Aug 2007) $ + */ +public class AbstractProcessorTest extends TestCase { + protected AssemblyFactory factory; + protected JavaInterfaceFactory javaFactory; + protected ConstructorProcessor constructorProcessor; + private ReferenceProcessor referenceProcessor; + private PropertyProcessor propertyProcessor; + private ResourceProcessor resourceProcessor; + + + protected AbstractProcessorTest() { + factory = new DefaultAssemblyFactory(); + javaFactory = new DefaultJavaInterfaceFactory(); + referenceProcessor = new ReferenceProcessor(factory, javaFactory); + propertyProcessor = new PropertyProcessor(factory); + resourceProcessor = new ResourceProcessor(factory); + constructorProcessor = new ConstructorProcessor(factory); + referenceProcessor = new ReferenceProcessor(factory, javaFactory); + propertyProcessor = new PropertyProcessor(factory); + } + + protected void visitConstructor(Constructor constructor, + JavaImplementation type) throws IntrospectionException { + constructorProcessor.visitConstructor(constructor, type); + JavaConstructorImpl definition = type.getConstructor(); + if (definition == null) { + definition = new JavaConstructorImpl(constructor); + type.getConstructors().put(constructor, definition); + } + JavaParameterImpl[] parameters = definition.getParameters(); + for (int i = 0; i < parameters.length; i++) { + referenceProcessor.visitConstructorParameter(parameters[i], type); + propertyProcessor.visitConstructorParameter(parameters[i], type); + resourceProcessor.visitConstructorParameter(parameters[i], type); + // monitorProcessor.visitConstructorParameter(parameters[i], type); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.java new file mode 100644 index 0000000000..809f992e7f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AbstractPropertyProcessorTestCase.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.implementation.java.introspect.impl; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty; + +import java.lang.annotation.Retention; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; + + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class AbstractPropertyProcessorTestCase extends TestCase { + + private JavaClassVisitor extension; + private JavaImplementationFactory javaImplementationFactory; + + public void testVisitMethod() throws Exception { + Method method = Foo.class.getMethod("setBar", String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + extension.visitMethod(method, type); + Property prop = getProperty(type, "test"); + assertNotNull(prop); + } + + public void testVisitNoParamsMethod() throws Exception { + Method method = Foo.class.getMethod("setNoParamsBar"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + extension.visitMethod(method, type); + fail(); + } catch (IllegalPropertyException e) { + // expected + } + } + + public void testVisitNonVoidMethod() throws Exception { + Method method = Foo.class.getMethod("setBadBar", String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + extension.visitMethod(method, type); + fail(); + } catch (IllegalPropertyException e) { + // expected + } + } + + public void testDuplicateMethod() throws Exception { + Method method = Foo.class.getMethod("setBar", String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + extension.visitMethod(method, type); + try { + extension.visitMethod(method, type); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testVisitField() throws Exception { + Field field = Foo.class.getDeclaredField("d"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + extension.visitField(field, type); + Property prop = getProperty(type, "test"); + assertNotNull(prop); + } + + public void testVisitConstructor() throws Exception { + Constructor ctor = Foo.class.getConstructor(String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + JavaConstructorImpl def = new JavaConstructorImpl(ctor); + JavaParameterImpl parameter = def.getParameters()[0]; + extension.visitConstructorParameter(parameter, type); + assertEquals("test", def.getParameters()[0].getName()); + assertNotNull(getProperty(type, "test")); + } + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + extension = new TestProcessor(); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + } + + @Retention(RUNTIME) + private @interface Bar { + + } + + private class TestProcessor extends AbstractPropertyProcessor { + + public TestProcessor() { + super(new DefaultAssemblyFactory(), Bar.class); + } + + @Override + @SuppressWarnings("unchecked") + protected void initProperty(Property property, Bar annotation) { + // property.setDefaultValueFactory(EasyMock.createMock(ObjectFactory.class)); + property.setName("test"); + } + + @Override + protected String getName(Bar annotation) { + return "test"; + } + } + + private static class Foo { + + @Bar + protected String d; + + public Foo(String a, @Bar + String b) { + } + + public Foo(@Bar + String d) { + this.d = d; + } + + @Bar + public void setBar(String d) { + this.d = d; + } + + @Bar + public void setNoParamsBar() { + } + + @Bar + public String setBadBar(String d) { + return null; + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.java new file mode 100644 index 0000000000..c48977d201 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/AllowsPassByReferenceProcessorTestCase.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.implementation.java.introspect.impl; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.AllowsPassByReference; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class AllowsPassByReferenceProcessorTestCase extends TestCase { + + JavaImplementation type; + AllowsPassByReferenceProcessor processor; + private JavaImplementationFactory javaImplementationFactory; + + public void testClassAnnotation() throws Exception { + processor.visitClass(Foo.class, type); + assertEquals(true, type.isAllowsPassByReference()); + + processor.visitClass(Bar.class, type); + assertEquals(false, type.isAllowsPassByReference()); + + Method m1 = Bar.class.getMethod("m1", new Class[] {}); + processor.visitMethod(m1, type); + assertTrue(type.isAllowsPassByReference(m1)); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + type = javaImplementationFactory.createJavaImplementation(); + processor = new AllowsPassByReferenceProcessor(new DefaultAssemblyFactory()); + } + + @AllowsPassByReference + private class Foo { + } + + // no annotation + private class Bar { + @AllowsPassByReference + public void m1() { + + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java new file mode 100644 index 0000000000..5be57dcca5 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorProcessorTestCase.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty; +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getReference; + +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; + +/** + * @version $Rev: 564364 $ $Date: 2007-08-09 13:14:52 -0700 (Thu, 09 Aug 2007) $ + */ +public class ConstructorProcessorTestCase extends TestCase { + private ConstructorProcessor processor = new ConstructorProcessor(new DefaultAssemblyFactory()); + + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testDuplicateConstructor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitClass(BadFoo.class, type); + fail(); + } catch (DuplicateConstructorException e) { + // expected + } + } + + public void testConstructorAnnotation() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor1 = Foo.class.getConstructor(String.class); + processor.visitConstructor(ctor1, type); + assertEquals("foo", type.getConstructor().getParameters()[0].getName()); + } + + public void testNoAnnotation() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor1 = NoAnnotation.class.getConstructor(); + processor.visitConstructor(ctor1, type); + assertNull(type.getConstructor()); + } + + public void testBadAnnotation() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor1 = BadAnnotation.class.getConstructor(String.class, Foo.class); + try { + processor.visitConstructor(ctor1, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + public void testMixedParameters() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor1 = Mixed.class.getConstructor(String.class, String.class, String.class); + processor.visitConstructor(ctor1, type); + + AssemblyFactory assemblyFactory = new DefaultAssemblyFactory(); + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + ReferenceProcessor referenceProcessor = new ReferenceProcessor(assemblyFactory, javaFactory); + PropertyProcessor propertyProcessor = new PropertyProcessor(assemblyFactory); + JavaParameterImpl[] parameters = type.getConstructor().getParameters(); + for (int i = 0; i < parameters.length; i++) { + referenceProcessor.visitConstructorParameter(parameters[i], type); + propertyProcessor.visitConstructorParameter(parameters[i], type); + } + + assertEquals("_ref0", parameters[0].getName()); + assertEquals("foo", parameters[1].getName()); + assertEquals("bar", parameters[2].getName()); + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor("foo") + public BadFoo(String foo) { + + } + + @org.osoa.sca.annotations.Constructor( {"foo", "bar"}) + public BadFoo(String foo, String bar) { + + } + } + + private static class Foo { + @org.osoa.sca.annotations.Constructor("foo") + public Foo(String foo) { + + } + } + + private static class NoAnnotation { + public NoAnnotation() { + } + } + + private static class BadAnnotation { + @org.osoa.sca.annotations.Constructor("foo") + public BadAnnotation(String foo, Foo ref) { + } + } + + public static final class Mixed { + @org.osoa.sca.annotations.Constructor + public Mixed(@Reference + String param1, @Property(name = "foo") + String param2, @Reference(name = "bar") + String param3) { + } + } + + public static final class Multiple { + @org.osoa.sca.annotations.Constructor + public Multiple(@Reference + Collection param1, @Property(name = "foo") + String[] param2, @Reference(name = "bar", required = true) + List param3, @Property(name = "abc") + Set param4, @Reference(name = "xyz") + String[] param5) { + } + } + + public void testMultiplicity() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor1 = Multiple.class.getConstructor(Collection.class, + String[].class, + List.class, + Set.class, + String[].class); + processor.visitConstructor(ctor1, type); + AssemblyFactory assemblyFactory = new DefaultAssemblyFactory(); + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + ReferenceProcessor referenceProcessor = new ReferenceProcessor(assemblyFactory, javaFactory); + PropertyProcessor propertyProcessor = new PropertyProcessor(assemblyFactory); + JavaParameterImpl[] parameters = type.getConstructor().getParameters(); + for (int i = 0; i < parameters.length; i++) { + referenceProcessor.visitConstructorParameter(parameters[i], type); + propertyProcessor.visitConstructorParameter(parameters[i], type); + } + + org.apache.tuscany.sca.assembly.Reference ref0 = getReference(type, "_ref0"); + assertNotNull(ref0); + assertEquals(Multiplicity.ONE_N, ref0.getMultiplicity()); + org.apache.tuscany.sca.assembly.Reference ref1 = getReference(type, "bar"); + assertNotNull(ref1); + assertEquals(Multiplicity.ONE_N, ref1.getMultiplicity()); + org.apache.tuscany.sca.assembly.Reference ref2 = getReference(type, "xyz"); + assertNotNull(ref2); + assertEquals(Multiplicity.ONE_N, ref2.getMultiplicity()); + org.apache.tuscany.sca.assembly.Property prop1 = getProperty(type, "foo"); + assertNotNull(prop1); + assertTrue(prop1.isMany()); + org.apache.tuscany.sca.assembly.Property prop2 = getProperty(type, "abc"); + assertNotNull(prop2); + assertTrue(prop2.isMany()); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java new file mode 100644 index 0000000000..252c7c725d --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorPropertyTestCase.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.Property; + +/** + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class ConstructorPropertyTestCase extends AbstractProcessorTest { + + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testProperty() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class); + visitConstructor(ctor, type); + org.apache.tuscany.sca.assembly.Property property = getProperty(type, "myProp"); + assertTrue(property.isMustSupply()); + assertEquals("myProp", property.getName()); + } + + public void testTwoPropertiesSameType() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class, String.class); + visitConstructor(ctor, type); + assertNotNull(getProperty(type, "myProp1")); + assertNotNull(getProperty(type, "myProp2")); + } + + public void testDuplicateProperty() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(String.class, String.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testNoName() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(String.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidPropertyException e) { + // expected + } + } + + public void testNamesOnConstructor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(Integer.class); + visitConstructor(ctor, type); + assertNotNull(getProperty(type, "myProp")); + } + + public void testInvalidNumberOfNames() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(Integer.class, Integer.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + public void testNoMatchingNames() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(List.class, List.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + +// public void testMultiplicityRequired() throws Exception { + // TODO multiplicity +// } + + private static class Foo { + + @org.osoa.sca.annotations.Constructor() + public Foo(@Property(name = "myProp", required = true)String prop) { + + } + + @org.osoa.sca.annotations.Constructor("myProp") + public Foo(@Property Integer prop) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Property(name = "myProp1")String prop1, @Property(name = "myProp2")String prop2) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Property List prop) { + + } + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor() + public BadFoo(@Property(name = "myProp")String prop1, @Property(name = "myProp")String prop2) { + + } + + @org.osoa.sca.annotations.Constructor() + public BadFoo(@Property String prop) { + + } + + @org.osoa.sca.annotations.Constructor("myProp") + public BadFoo(@Property Integer prop, @Property Integer prop2) { + + } + + @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"}) + public BadFoo(@Property List ref, @Property(name = "myOtherRef")List ref2) { + + } + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.java new file mode 100644 index 0000000000..c794b0a800 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorReferenceTestCase.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.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getReference; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.Reference; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ConstructorReferenceTestCase extends AbstractProcessorTest { + + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testReference() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class); + visitConstructor(ctor, type); + org.apache.tuscany.sca.assembly.Reference reference = getReference(type, "myRef"); + assertEquals(Multiplicity.ONE_ONE, reference.getMultiplicity()); + assertEquals("myRef", reference.getName()); + } + + public void testTwoReferencesSameType() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class, String.class); + visitConstructor(ctor, type); + assertNotNull(getReference(type, "myRef1")); + assertNotNull(getReference(type, "myRef2")); + } + + public void testDuplicateProperty() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(String.class, String.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (DuplicateReferenceException e) { + // expected + } + } + + public void testNoName() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = NoNameFoo.class.getConstructor(String.class); + visitConstructor(ctor, type); + assertNotNull(getReference(type, "_ref0")); + } + + public void testNamesOnConstructor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(Integer.class); + visitConstructor(ctor, type); + assertNotNull(getReference(type, "myRef")); + } + + public void testInvalidNumberOfNames() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(Integer.class, Integer.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + public void testNoMatchingNames() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(List.class, List.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + +// public void testMultiplicityRequired() throws Exception { + // TODO multiplicity +// } + + private static class Foo { + + @org.osoa.sca.annotations.Constructor() + public Foo(@Reference(name = "myRef", required = true)String prop) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Reference(name = "myRef1")String prop1, @Reference(name = "myRef2")String prop2) { + + } + + @org.osoa.sca.annotations.Constructor("myRef") + public Foo(@Reference Integer prop) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Reference List prop) { + + } + } + + private static class NoNameFoo { + + @org.osoa.sca.annotations.Constructor + public NoNameFoo(@Reference String prop) { + + } + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor + public BadFoo(@Reference(name = "myRef")String prop1, @Reference(name = "myRef")String prop2) { + + } + + @org.osoa.sca.annotations.Constructor + public BadFoo(@Reference String prop) { + + } + + @org.osoa.sca.annotations.Constructor("myRef") + public BadFoo(@Reference Integer ref, @Reference Integer ref2) { + + } + + @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"}) + public BadFoo(@Reference List ref, @Reference(name = "myOtherRef")List ref2) { + + } + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java new file mode 100644 index 0000000000..e35168180c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConstructorResourceTestCase.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; + +/** + * @version $Rev: 563019 $ $Date: 2007-08-05 20:43:59 -0700 (Sun, 05 Aug 2007) $ + */ +public class ConstructorResourceTestCase extends AbstractProcessorTest { + + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testResource() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class); + visitConstructor(ctor, type); + org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl resource = type.getResources().get("myResource"); + assertFalse(resource.isOptional()); + } + + public void testTwoResourcesSameType() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class, String.class); + visitConstructor(ctor, type); + assertNotNull(type.getResources().get("myResource1")); + assertNotNull(type.getResources().get("myResource2")); + } + + public void testDuplicateResource() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = BadFoo.class.getConstructor(String.class, String.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (DuplicateResourceException e) { + // expected + } + } + + public void testNoName() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = + ConstructorResourceTestCase.BadFoo.class.getConstructor(String.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidResourceException e) { + // expected + } + } + + public void testNamesOnConstructor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(Integer.class); + visitConstructor(ctor, type); + assertNotNull(type.getResources().get("myResource")); + } + + public void testInvalidNumberOfNames() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = + ConstructorResourceTestCase.BadFoo.class.getConstructor(Integer.class, Integer.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + public void testNoMatchingNames() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = + ConstructorResourceTestCase.BadFoo.class.getConstructor(List.class, List.class); + try { + visitConstructor(ctor, type); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + private static class Foo { + + @org.osoa.sca.annotations.Constructor + public Foo(@Resource(name = "myResource") String resource) { + + } + + @org.osoa.sca.annotations.Constructor("myResource") + public Foo(@Resource Integer resource) { + + } + + @org.osoa.sca.annotations.Constructor + public Foo(@Resource(name = "myResource1") String res1, @Resource(name = "myResource2") String res2) { + + } + + @org.osoa.sca.annotations.Constructor + public Foo(@Resource List res) { + + } + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor + public BadFoo(@Resource(name = "myResource") String res1, @Resource(name = "myResource") String res2) { + + } + + @org.osoa.sca.annotations.Constructor + public BadFoo(@Resource String res) { + + } + + @org.osoa.sca.annotations.Constructor("myProp") + public BadFoo(@Resource Integer res, @Resource Integer res2) { + + } + + @org.osoa.sca.annotations.Constructor({"myRes", "myRes2"}) + public BadFoo(@Resource List res, @Resource(name = "myOtherRes") List res2) { + + } + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java new file mode 100644 index 0000000000..d1dfb2fb0c --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ContextProcessorTestCase.java @@ -0,0 +1,201 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.annotations.ComponentName; +import org.osoa.sca.annotations.Context; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ContextProcessorTestCase extends TestCase { + private ContextProcessor processor; + private ComponentNameProcessor nameProcessor; + private JavaImplementationFactory javaImplementationFactory; + + public void testComponentContextMethod() throws Exception { + Method method = Foo.class.getMethod("setContext", ComponentContext.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitMethod(method, type); + assertNotNull(type.getResources().get("context")); + } + + public void testComponentContextField() throws Exception { + Field field = Foo.class.getDeclaredField("context"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitField(field, type); + assertNotNull(type.getResources().get("context")); + } + + public void testRequestContextMethod() throws Exception { + Method method = Foo.class.getMethod("setRequestContext", RequestContext.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitMethod(method, type); + assertNotNull(type.getResources().get("requestContext")); + } + + public void testRequestContextField() throws Exception { + Field field = Foo.class.getDeclaredField("requestContext"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitField(field, type); + assertNotNull(type.getResources().get("requestContext")); + } + + public void testComponentNameMethod() throws Exception { + Method method = Foo.class.getMethod("setName", String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + nameProcessor.visitMethod(method, type); + assertNotNull(type.getResources().get("name")); + } + + public void testComponentNameField() throws Exception { + Field field = Foo.class.getDeclaredField("name"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + nameProcessor.visitField(field, type); + assertNotNull(type.getResources().get("name")); + } + + public void testInvalidParamType() throws Exception { + Method method = Foo.class.getMethod("setContext", String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitMethod(method, type); + fail(); + } catch (UnknownContextTypeException e) { + // expected + } + } + + public void testInvalidParamTypeField() throws Exception { + Field field = Foo.class.getDeclaredField("badContext"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitField(field, type); + fail(); + } catch (UnknownContextTypeException e) { + // expected + } + } + + + public void testInvalidParamNum() throws Exception { + Method method = Foo.class.getMethod("setContext", ComponentContext.class, String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalContextException e) { + // expected + } + } + + public void testInvalidNoParams() throws Exception { + Method method = Foo.class.getMethod("setContext"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalContextException e) { + // expected + } + } + + public void testNoContext() throws Exception { + Method method = Foo.class.getMethod("noContext", ComponentContext.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitMethod(method, type); + assertEquals(0, type.getResources().size()); + } + + public void testNoContextField() throws Exception { + Field field = Foo.class.getDeclaredField("noContext"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitField(field, type); + assertEquals(0, type.getResources().size()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + processor = new ContextProcessor(new DefaultAssemblyFactory()); + nameProcessor = new ComponentNameProcessor(new DefaultAssemblyFactory()); + } + + private class Foo { + @Context + protected ComponentContext context; + + @ComponentName + protected String name; + + @Context + protected Object badContext; + + protected ComponentContext noContext; + + @Context + protected RequestContext requestContext; + + @Context + public void setContext(ComponentContext context) { + + } + + @ComponentName + public void setName(String name) { + + } + + @Context + public void setContext(String context) { + + } + + @Context + public void setContext(ComponentContext context, String string) { + + } + + @Context + public void setContext() { + + } + + public void noContext(ComponentContext context) { + + } + + @Context + public void setRequestContext(RequestContext requestContext) { + this.requestContext = requestContext; + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessorTestCase.java new file mode 100644 index 0000000000..3df561ef33 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationIDProcessorTestCase.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.ConversationID; + +/** + * Test the ConversationIDProcessor + */ +public class ConversationIDProcessorTestCase extends TestCase { + private ConversationIDProcessor processor; + private JavaImplementationFactory javaImplementationFactory; + + public void testConversationIDMethod() throws Exception { + Method method = Foo.class.getMethod("setConversationID", String.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitMethod(method, type); + assertNotNull(type.getResources().get("conversationID")); + } + + public void testConversationIDField() throws Exception { + Field field = Foo.class.getDeclaredField("cid"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitField(field, type); + assertNotNull(type.getResources().get("cid")); + } + + public void testConversationIDMethodNotString() throws Exception { + Method method = Foo.class.getMethod("setConversationID", Long.class); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitMethod(method, type); + assertNotNull(type.getResources().get("conversationID")); + } + + public void testConversationIDFieldNotString() throws Exception { + Field field = Foo.class.getDeclaredField("longCID"); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitField(field, type); + assertNotNull(type.getResources().get("longCID")); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + processor = new ConversationIDProcessor(new DefaultAssemblyFactory()); + } + + private class Foo { + + @ConversationID + protected String cid; + + @ConversationID + public void setConversationID(String cid) { + + } + + @ConversationID + protected Long longCID; + + @ConversationID + public void setConversationID(Long cid) { + + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java new file mode 100644 index 0000000000..6dc91bec22 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConversationProcessorTestCase.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.ConversationAttributes; +import org.osoa.sca.annotations.ConversationID; +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev: 620333 $ $Date: 2008-02-10 13:31:04 -0800 (Sun, 10 Feb 2008) $ + */ +public class ConversationProcessorTestCase extends TestCase { + private ConversationProcessor processor = new ConversationProcessor(new DefaultAssemblyFactory()); + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testMaxIdleTime() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(FooMaxIdle.class, type); + assertEquals(10000L, type.getMaxIdleTime()); + assertEquals(-1, type.getMaxAge()); + } + + public void testMaxAge() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(FooMaxAge.class, type); + assertEquals(10000L, type.getMaxAge()); + assertEquals(-1, type.getMaxIdleTime()); + } + + public void testImplicitScope() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(ImplicitFooScope.class, type); + assertEquals(org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl.CONVERSATION, type.getJavaScope()); + } + + /* TUSCANY-1999 - apply conversation properties to all scopes + public void testBadFooScope() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitClass(BadFooScope.class, type); + fail(); + } catch (InvalidConversationalImplementation e) { + // expected + } + } + */ + + public void testBadFooBoth() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(BadFooBoth.class, type); + assertEquals(10000L, type.getMaxAge()); + assertEquals(10000L, type.getMaxIdleTime()); + } + + public void testJustConversation() throws Exception { + // TODO do we want these semantics + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(FooJustConversation.class, type); + assertEquals(org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl.CONVERSATION, type.getJavaScope()); + assertEquals(-1, type.getMaxAge()); + assertEquals(-1, type.getMaxIdleTime()); + } + + public void testSetConversationIDField() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Field field = FooWithConversationIDField.class.getDeclaredField("conversationID"); + processor.visitField(field, type); + assertNotNull(type.getConversationIDMembers()); + assertEquals(field, type.getConversationIDMembers().get(0)); + } + + public void testSetConversationIDMethod() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = FooWithConversationIDMethod.class.getDeclaredMethods()[0]; + processor.visitMethod(method, type); + assertNotNull(type.getConversationIDMembers()); + assertEquals(method, type.getConversationIDMembers().get(0)); + } + + @Scope("CONVERSATION") + @ConversationAttributes(maxIdleTime = "10 seconds") + private class FooMaxIdle { + } + + @Scope("CONVERSATION") + @ConversationAttributes(maxAge = "10 seconds") + private class FooMaxAge { + } + + @Scope("CONVERSATION") + @ConversationAttributes(maxAge = "10 seconds", maxIdleTime = "10 seconds") + private class BadFooBoth { + } + + @ConversationAttributes(maxAge = "10 seconds") + private class ImplicitFooScope { + } + + @Scope("STATELESS") + @ConversationAttributes(maxAge = "10 seconds") + private class BadFooScope { + } + + @ConversationAttributes + private class FooJustConversation { + } + + private class FooWithConversationIDField { + + @ConversationID + String conversationID; + } + + private class FooWithConversationIDMethod { + @ConversationID + void setConversationID(String conversationID) { + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.java new file mode 100644 index 0000000000..41d277e377 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ConvertTimeMillisTestCase.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.implementation.java.introspect.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ConvertTimeMillisTestCase extends TestCase { + private MockProcessor registy; + + public void testConvertSeconds() throws Exception { + assertEquals(10000L, registy.convertTimeMillis("10 seconds")); + assertEquals(10000L, registy.convertTimeMillis("10 SECONDS")); + try { + registy.convertTimeMillis("10seconds"); + fail(); + } catch (NumberFormatException e) { + // expected + } + } + + public void testConvertMinutes() throws Exception { + assertEquals(600000L, registy.convertTimeMillis("10 minutes")); + assertEquals(600000L, registy.convertTimeMillis("10 MINUTES")); + try { + registy.convertTimeMillis("10minutes"); + fail(); + } catch (NumberFormatException e) { + // expected + } + } + + public void testConvertHours() throws Exception { + assertEquals(36000000L, registy.convertTimeMillis("10 hours")); + assertEquals(36000000L, registy.convertTimeMillis("10 HOURS")); + try { + registy.convertTimeMillis("10hours"); + fail(); + } catch (NumberFormatException e) { + // expected + } + } + + public void testConvertDays() throws Exception { + assertEquals(864000000L, registy.convertTimeMillis("10 days")); + assertEquals(864000000L, registy.convertTimeMillis("10 DAYS")); + try { + registy.convertTimeMillis("10days"); + fail(); + } catch (NumberFormatException e) { + // expected + } + } + + public void testConvertYears() throws Exception { + assertEquals(315569260000L, registy.convertTimeMillis("10 years")); + assertEquals(315569260000L, registy.convertTimeMillis("10 YEARS")); + try { + registy.convertTimeMillis("10years"); + fail(); + } catch (NumberFormatException e) { + // expected + } + } + + public void testConvertDefault() throws Exception { + assertEquals(10000L, registy.convertTimeMillis("10 ")); + assertEquals(10000L, registy.convertTimeMillis("10")); + } + + public void testInvalid() throws Exception { + try { + registy.convertTimeMillis("foo"); + fail(); + } catch (NumberFormatException e) { + // expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + registy = new MockProcessor(); + } + + private class MockProcessor extends ConversationProcessor { + + public MockProcessor() { + super(new DefaultAssemblyFactory()); + } + + @Override + protected long convertTimeMillis(String expr) throws NumberFormatException { + return super.convertTimeMillis(expr); + } + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java new file mode 100644 index 0000000000..5ff99b1265 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/DestroyProcessorTestCase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.Destroy; + +/** + * @version $Rev: 563019 $ $Date: 2007-08-05 20:43:59 -0700 (Sun, 05 Aug 2007) $ + */ +public class DestroyProcessorTestCase extends TestCase { + + private AssemblyFactory assemblyFactory = new DefaultAssemblyFactory(); + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testDestroy() throws Exception { + DestroyProcessor processor = new DestroyProcessor(assemblyFactory); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = Foo.class.getMethod("destroy"); + processor.visitMethod(method, type); + assertNotNull(type.getDestroyMethod()); + } + + public void testBadDestroy() throws Exception { + DestroyProcessor processor = new DestroyProcessor(assemblyFactory); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = Bar.class.getMethod("badDestroy", String.class); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalDestructorException e) { + // expected + } + } + + public void testTwoDestroy() throws Exception { + DestroyProcessor processor = new DestroyProcessor(assemblyFactory); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = Bar.class.getMethod("destroy"); + Method method2 = Bar.class.getMethod("destroy2"); + processor.visitMethod(method, type); + try { + processor.visitMethod(method2, type); + fail(); + } catch (DuplicateDestructorException e) { + // expected + } + } + + + private class Foo { + + @Destroy + public void destroy() { + } + } + + + private class Bar { + + @Destroy + public void destroy() { + } + + @Destroy + public void destroy2() { + } + + @Destroy + public void badDestroy(String foo) { + } + + + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java new file mode 100644 index 0000000000..032b821c79 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/EagerInitProcessorTestCase.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.EagerInit; + +/** + * @version $Rev: 563061 $ $Date: 2007-08-06 01:19:58 -0700 (Mon, 06 Aug 2007) $ + */ +public class EagerInitProcessorTestCase extends TestCase { + + private AssemblyFactory assemblyFactory = new DefaultAssemblyFactory(); + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + public void testNoLevel() throws IntrospectionException { + EagerInitProcessor processor = new EagerInitProcessor(assemblyFactory); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(Level.class, type); + } + + public void testSubclass() throws IntrospectionException { + EagerInitProcessor processor = new EagerInitProcessor(assemblyFactory); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(SubClass.class, type); + } + + @EagerInit + private class Level { + } + + private class SubClass extends Level { + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.java new file mode 100644 index 0000000000..dac4d1864f --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicAndPropertyTestCase.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.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.osoa.sca.annotations.Property; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class HeuristicAndPropertyTestCase extends TestCase { + + private PropertyProcessor propertyProcessor; + private HeuristicPojoProcessor heuristicProcessor; + private AssemblyFactory assemblyFactory = new DefaultAssemblyFactory(); + private JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + + /** + * Verifies the property and heuristic processors don't collide + */ + @SuppressWarnings("unchecked") + public void testPropertyProcessorWithHeuristicProcessor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class); + type.setConstructor(new JavaConstructorImpl(ctor)); + propertyProcessor.visitConstructorParameter(type.getConstructor().getParameters()[0], type); + heuristicProcessor.visitEnd(Foo.class, type); + assertEquals(1, type.getProperties().size()); + assertEquals("foo", type.getProperties().get(0).getName()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + propertyProcessor = new PropertyProcessor(assemblyFactory); + heuristicProcessor = new HeuristicPojoProcessor(assemblyFactory, new DefaultJavaInterfaceFactory()); + } + + public static class Foo { + public Foo(@Property(name = "foo") + String prop) { + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java new file mode 100644 index 0000000000..48c11c5c87 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicConstructorTestCase.java @@ -0,0 +1,310 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty; + +import java.lang.reflect.Constructor; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; + +/** + * @version $Rev: 570495 $ $Date: 2007-08-28 10:32:53 -0700 (Tue, 28 Aug 2007) $ + */ +public class HeuristicConstructorTestCase extends AbstractProcessorTest { + + private AssemblyFactory factory; + private JavaInterfaceFactory javaFactory; + private HeuristicPojoProcessor processor; + private JavaImplementationFactory javaImplementationFactory; + + public HeuristicConstructorTestCase() { + factory = new DefaultAssemblyFactory(); + javaFactory = new DefaultJavaInterfaceFactory(); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + processor = new HeuristicPojoProcessor(factory, javaFactory); + } + + private void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + for (Constructor constructor : clazz.getConstructors()) { + visitConstructor(constructor, type); + } + processor.visitEnd(clazz, type); + } + + /** + * Verifies a single constructor is chosen with a parameter as the type + */ + public void testSingleConstructorWithParam() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + org.apache.tuscany.sca.assembly.Property prop = factory.createProperty(); + prop.setName("foo"); + type.getProperties().add(prop); + // Hack to add a property member + JavaElementImpl element = new JavaElementImpl("foo", String.class, null); + type.getPropertyMembers().put("foo", element); + visitEnd(Foo1.class, type); + assertNotNull(type.getConstructor().getConstructor()); + assertEquals("foo", type.getConstructor().getParameters()[0].getName()); + } + + /** + * Verifies a single constructor is chosen with a reference as the type + */ + public void testSingleConstructorWithRef() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + org.apache.tuscany.sca.assembly.Reference ref = factory.createReference(); + ref.setName("foo"); + type.getReferences().add(ref); + type.getReferenceMembers().put("foo", new JavaElementImpl("foo", String.class, null)); + visitEnd(Foo1.class, type); + assertNotNull(type.getConstructor().getConstructor()); + assertEquals("foo", type.getConstructor().getParameters()[0].getName()); + } + + /** + * Verifies a single constructor is chosen with a property and a reference + * as the type + */ + public void testSingleConstructorWithPropRef() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + + org.apache.tuscany.sca.assembly.Property prop = factory.createProperty(); + prop.setName("foo"); + type.getProperties().add(prop); + // Hack to add a property member + JavaElementImpl element = new JavaElementImpl("foo", String.class, null); + type.getPropertyMembers().put("foo", element); + + org.apache.tuscany.sca.assembly.Reference ref = ModelHelper.createReference(factory, javaFactory, "ref", Foo1.class); + type.getReferences().add(ref); + type.getReferenceMembers().put("ref", new JavaElementImpl("ref", Foo1.class, null)); + visitEnd(Foo2.class, type); + assertNotNull(type.getConstructor().getConstructor()); + assertEquals(2, type.getConstructor().getParameters().length); + } + + public void testSingleConstructorResolvableParam() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo5.class, type); + assertEquals(String.class, type.getPropertyMembers().get("string").getType()); + } + + public void testSingleConstructorResolvableRef() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo6.class, type); + assertTrue(ModelHelper.matches(ModelHelper.getReference(type, "ref"), Ref.class)); + } + + public void testSingleConstructorAmbiguousRef() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + org.apache.tuscany.sca.assembly.Reference ref = ModelHelper.createReference(factory, javaFactory, "ref", Foo1.class); + type.getReferences().add(ref); + type.getReferenceMembers().put("ref", new JavaElementImpl("ref", Foo1.class, null)); + org.apache.tuscany.sca.assembly.Reference ref2 = ModelHelper.createReference(factory, javaFactory, "ref2", Foo1.class); + type.getReferences().add(ref2); + type.getReferenceMembers().put("ref2", new JavaElementImpl("ref2", Foo1.class, null)); + try { + visitEnd(Foo4.class, type); + fail(); + } catch (AmbiguousConstructorException e) { + // expected + } + } + + public void testConstructorPropertyAnnotatedParamsOnly() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo7.class, type); + assertNotNull(getProperty(type, "myProp")); + } + + public void testConstructorReferenceAnnotatedParamsOnly() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo8.class, type); + assertNotNull(ModelHelper.getReference(type, "myRef")); + } + + @SuppressWarnings("unchecked") + public void testDefaultConstructor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo3.class, type); + assertNotNull(type.getConstructor().getConstructor()); + } + + public void testSameTypesButAnnotated() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo12.class, type); + assertEquals(2, type.getProperties().size()); + assertNotNull(getProperty(type, "prop1")); + assertNotNull(getProperty(type, "prop2")); + } + + /** + * Verifies processing executes with additional extension annotations + */ + public void testRandomAnnotation() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo11.class, type); + assertEquals(1, type.getProperties().size()); + assertNotNull(getProperty(type, "prop1")); + } + + public void testPrivateConstructor() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + visitEnd(Foo14.class, type); + fail(); + } catch (NoConstructorException e) { + // expected + } + } + + public void testMultipleConstructors() throws Exception { + // throw new UnsupportedOperationException("Finish heuristic multiple + // constructors - Foo10"); + } + + public static class Foo1 { + public Foo1(String val) { + } + } + + public static class Foo2 { + public Foo2(String val, Foo1 ref) { + } + } + + public static class Foo3 { + } + + public static class Foo4 { + public Foo4(Foo1 ref) { + } + } + + public static class Prop { + + } + + @Remotable + public static interface Ref { + + } + + public static class Foo5 { + public Foo5(String val) { + } + } + + public static class Foo6 { + public Foo6(Ref ref) { + } + } + + public static class Foo7 { + public Foo7(@Property(name = "myProp") + String prop) { + } + } + + public static class Foo8 { + public Foo8(@Reference(name = "myRef") + String ref) { + } + } + + public static class Foo9 { + public Foo9(@Reference(name = "myRef") + String ref) { + } + } + + public static class Foo10 { + + public Foo10() { + } + + public Foo10(String prop) { + } + + public Foo10(@Property(name = "prop1") + String prop1, @Property(name = "prop2") + String prop2) { + + } + } + + public static class Foo11 { + + public Foo11(@Property(name = "prop1") + String prop, @Baz + String baz) { + } + } + + public static class Foo12 { + + public Foo12(@Property(name = "prop1") + String prop, @Property(name = "prop2") + String baz) { + } + } + + public @interface Baz { + + } + + public static class Foo13 { + public Foo13(@Reference + String foo) { + } + } + + public static final class Foo14 { + private Foo14() { + } + } + + public static final class Foo15 { + public Foo15(@Reference + String param1, @Reference + String param2) { + } + } + + public static final class Foo16 { + public Foo16(@Reference + String param1, @Property(name = "foo") + String param2, @Reference(name = "bar") + String param3) { + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java new file mode 100644 index 0000000000..976de72ae7 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeuristicPojoProcessorTestCase.java @@ -0,0 +1,407 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; + +/** + * Verifies component type information is properly introspected from an unadorned + * POJO according to the SCA Java Client and Implementation Model Specification + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public class HeuristicPojoProcessorTestCase extends AbstractProcessorTest { + + private org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor processor; + private JavaImplementationFactory javaImplementationFactory; + + public HeuristicPojoProcessorTestCase() { + processor = new HeuristicPojoProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory()); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + } + + private void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + for (Constructor constructor : clazz.getConstructors()) { + visitConstructor(constructor, type); + } + processor.visitEnd(clazz, type); + } + + /** + * Verifies a single service interface is computed when only one interface + * is implemented + */ + public void testSingleInterface() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = SingleInterfaceImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(SingleInterfaceImpl.class, type); + assertEquals(1, type.getServices().size()); + assertTrue(ModelHelper.matches(ModelHelper.getService(type, PropertyInterface.class.getSimpleName()), + PropertyInterface.class)); + assertTrue(type.getProperties().isEmpty()); + assertTrue(type.getReferences().isEmpty()); + } + + /** + * Verifies property and reference setters are computed + */ + public void testPropertyReference() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = SingleInterfaceWithPropertyReferenceImpl.class + .getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(SingleInterfaceWithPropertyReferenceImpl.class, type); + assertEquals(1, type.getServices().size()); + assertTrue(ModelHelper + .matches(ModelHelper.getService(type, Interface1.class.getSimpleName()), Interface1.class)); + assertEquals(1, type.getProperties().size()); + org.apache.tuscany.sca.assembly.Property prop = ModelHelper.getProperty(type, "property"); + assertNotNull(prop); + assertEquals(ComplexProperty.class, type.getPropertyMembers().get("property").getType()); + assertEquals(1, type.getReferences().size()); + assertTrue(ModelHelper.matches(ModelHelper.getReference(type, "reference"), Ref.class)); + } + + /** + * Verifies that a property setter is not introspected if an analogous + * operation is in the service interface + */ + public void testPropertySetterInInterface() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = SingleInterfaceImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(SingleInterfaceImpl.class, type); + assertEquals(0, type.getProperties().size()); + } + + /** + * Verifies that a reference setter is not introspected if an analogous + * operation is in the service interface + */ + public void testReferenceSetterInInterface() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = RefInterfaceImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(RefInterfaceImpl.class, type); + assertEquals(0, type.getReferences().size()); + } + + /** + * Verifies collection generic types or array types are introspected as + * references according to specification rules + */ + public void testReferenceCollectionType() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = ReferenceCollectionImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(ReferenceCollectionImpl.class, type); + assertEquals(1, type.getProperties().size()); + assertEquals(3, type.getReferences().size()); + } + + /** + * Verifies collection generic types or array types are introspected as + * properties according to specification rules + */ + public void testPropertyCollectionType() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = PropertyCollectionImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(PropertyCollectionImpl.class, type); + assertEquals(0, type.getReferences().size()); + assertEquals(4, type.getProperties().size()); + } + + /** + * Verifies references are calculated when the type marked with is + * + * @Remotable + */ + public void testRemotableRef() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = RemotableRefImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(RemotableRefImpl.class, type); + assertEquals(2, type.getReferences().size()); + assertEquals(0, type.getProperties().size()); + } + + public void testParentInterface() throws IntrospectionException, NoSuchMethodException { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Child.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(Child.class, type); + assertNotNull(ModelHelper.getService(type, Interface1.class.getSimpleName())); + } + + /** + * Verifies a service interface is calculated when only props and refs are + * given + */ + public void testExcludedPropertyAndReference() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + org.apache.tuscany.sca.assembly.Reference ref = factory.createReference(); + ref.setName("reference"); + type.getReferences().add(ref); + type.getReferenceMembers().put("reference", new JavaElementImpl("reference", Ref.class, null)); + org.apache.tuscany.sca.assembly.Reference ref2 = factory.createReference(); + ref2.setName("reference2"); + type.getReferences().add(ref2); + type.getReferenceMembers().put("reference2", new JavaElementImpl("reference2", Ref.class, null)); + org.apache.tuscany.sca.assembly.Property prop1 = factory.createProperty(); + prop1.setName("string1"); + type.getProperties().add(prop1); + type.getPropertyMembers().put("string1", new JavaElementImpl("string1", String.class, null)); + org.apache.tuscany.sca.assembly.Property prop2 = factory.createProperty(); + prop2.setName("string2"); + type.getProperties().add(prop2); + type.getPropertyMembers().put("string2", new JavaElementImpl("string2", String.class, null)); + visitEnd(MockService.class, type); + assertEquals(1, type.getServices().size()); + } + + public void testProtectedRemotableRefField() throws IntrospectionException, NoSuchMethodException { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = ProtectedRemotableRefFieldImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(ProtectedRemotableRefFieldImpl.class, type); + assertNotNull(ModelHelper.getReference(type, "otherRef")); + } + + public void testProtectedRemotableRefMethod() throws IntrospectionException, NoSuchMethodException { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = ProtectedRemotableRefMethodImpl.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(ProtectedRemotableRefMethodImpl.class, type); + assertNotNull(ModelHelper.getReference(type, "otherRef")); + } + + public void testSetDataTypes() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = PropertyIntTypeOnConstructor.class.getConstructor(); + type.setConstructor(new JavaConstructorImpl(ctor)); + processor.visitEnd(PropertyIntTypeOnConstructor.class, type); + org.apache.tuscany.sca.assembly.Property foo = ModelHelper.getProperty(type, "foo"); + assertEquals(int.class, type.getPropertyMembers().get("foo").getType()); + assertEquals(new QName(JavaXMLMapper.URI_2001_SCHEMA_XSD, "int"), foo.getXSDType()); + } + + private static class PropertyIntTypeOnConstructor { + protected int foo; + + public PropertyIntTypeOnConstructor() { + } + + public int getFoo() { + return foo; + } + } + + @Remotable + private interface PropertyInterface { + void setString1(String val); + } + + @Remotable + private interface Interface1 { + } + + private static class Parent implements Interface1 { + + } + + private static class Child extends Parent { + public Child() { + } + + } + + private static class SingleInterfaceImpl implements PropertyInterface { + public SingleInterfaceImpl() { + } + + public void setString1(String val) { + } + + } + + private interface HeuristicServiceInterface { + void fooOperation(String ref); + + void setInvalid1(); // No parameter + + void setInvalid2(String str, int i); // More than one parameter + + String setInvalid3(String str); // return should be void + } + + public static class MockService implements PropertyInterface, RefInterface, HeuristicServiceInterface { + + @Property + public void setString1(String val) { + } + + @Property + public void setString2(String val) { + } + + @Reference + public void setReference(Ref ref) { + } + + @Reference + public void setReference2(Ref ref) { + } + + public void fooOperation(String ref) { + + } + + public void setInvalid1() { + } + + public void setInvalid2(String str, int i) { + } + + public String setInvalid3(String str) { + return null; + } + + } + + @Remotable + private interface Ref { + } + + private class ComplexProperty { + } + + private interface RefInterface { + void setReference(Ref ref); + } + + private static class RefInterfaceImpl implements RefInterface { + public RefInterfaceImpl() { + } + + public void setReference(Ref ref) { + } + } + + private static class SingleInterfaceWithPropertyReferenceImpl implements Interface1 { + public SingleInterfaceWithPropertyReferenceImpl() { + } + + public void setReference(Ref ref) { + } + + public void setProperty(ComplexProperty prop) { + } + } + + private static class ReferenceCollectionImpl implements Interface1 { + public ReferenceCollectionImpl() { + } + + public void setCollectionReference(Collection ref) { + } + + public void setNonGenericCollectionReference(Collection ref) { + // [rfeng] By the SCA specification, this should be classified as property + } + + public void setListReference(List ref) { + } + + public void setArrayReference(Ref[] ref) { + } + } + + private static class PropertyCollectionImpl implements Interface1 { + public PropertyCollectionImpl() { + } + + public void setCollectionProperty(Collection prop) { + } + + public void setCollectionProperty2(Collection prop) { + } + + public void setArrayProperty(ComplexProperty[] prop) { + } + + public void setArrayProperty2(String[] prop) { + } + } + + @Remotable + private interface RemotableRef { + } + + private static class RemotableRefImpl implements Interface1 { + protected RemotableRef otherRef; + + public RemotableRefImpl() { + } + + public void setRef(RemotableRef ref) { + + } + } + + private static class ProtectedRemotableRefFieldImpl implements Interface1 { + protected RemotableRef otherRef; + + public ProtectedRemotableRefFieldImpl() { + } + + public ProtectedRemotableRefFieldImpl(RemotableRef otherRef) { + this.otherRef = otherRef; + } + + } + + private static class ProtectedRemotableRefMethodImpl implements Interface1 { + public ProtectedRemotableRefMethodImpl() { + } + + protected void setOtherRef(RemotableRef otherRef) { + } + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java new file mode 100644 index 0000000000..9fb7b57f2e --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/HeutisticExtensibleConstructorTestCase.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; + +/** + * Verifies constructors that have extensible annotation types, i.e. that have + * parameters marked by annotations which are themselves processed by some other + * implementation processor + * + * @version $Rev: 639634 $ $Date: 2008-03-21 05:33:46 -0800 (Fri, 21 Mar 2008) $ + */ +public class HeutisticExtensibleConstructorTestCase extends AbstractProcessorTest { + + private org.apache.tuscany.sca.implementation.java.introspect.impl.HeuristicPojoProcessor processor; + private JavaImplementationFactory javaImplementationFactory; + + public HeutisticExtensibleConstructorTestCase() { + processor = new HeuristicPojoProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory()); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + } + + private void visitEnd(Class clazz, JavaImplementation type) throws IntrospectionException { + for (Constructor constructor : clazz.getConstructors()) { + visitConstructor(constructor, type); + } + processor.visitEnd(clazz, type); + } + + /** + * Verifies heuristic processing can be called prior to an extension + * annotation processors being called. + */ + public void testBarAnnotationProcessedFirst() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo.class.getConstructor(String.class, String.class); + JavaConstructorImpl definition = new JavaConstructorImpl(ctor); + type.setConstructor(definition); + Property property = factory.createProperty(); + property.setName("myBar"); + definition.getParameters()[0].setName("myBar"); + type.getProperties().add(property); + visitEnd(Foo.class, type); + assertEquals(2, type.getProperties().size()); + } + + /** + * Verifies heuristic processing can be called before an extension + * annotation processors is called.

For example, given: + * + *

+     *  Foo(@Bar String prop, @org.osoa.sca.annotations.Property(name = "foo") String prop2)
+     * 
+ * + *

Heuristic evaluation of + * @Property can occur prior to another implementation processor evaluating + * @Bar + * @throws Exception + */ + public void testBarAnnotationProcessedLast() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + visitEnd(Foo.class, type); + + // now simulate process the bar impl + JavaConstructorImpl definition = type.getConstructor(); + definition.getParameters()[0].setName("myBar"); + Property property = factory.createProperty(); + property.setName("myBar"); + type.getProperties().add(property); + + assertEquals(2, type.getProperties().size()); + assertEquals("foo", definition.getParameters()[1].getName()); + } + + /** + * Verifies heuristic processing can be called before an extension + * annotation processors is called with the extension parameter in a middle + * position. Specifically, verifies that the heuristic processor updates + * injection names and preserves their ordering. + */ + public void testBarAnnotationProcessedFirstInMiddle() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Constructor ctor = Foo2.class.getConstructor(String.class, String.class, String.class); + JavaConstructorImpl definition = new JavaConstructorImpl(ctor); + type.setConstructor(definition); + // insert placeholder for first param, which would be done by a + // processor + definition.getParameters()[0].setName(""); + Property property = factory.createProperty(); + // Hack to add a property member + JavaElementImpl element = new JavaElementImpl("myBar", String.class, null); + type.getPropertyMembers().put("myBar", element); + property.setName("myBar"); + definition.getParameters()[1].setName("myBar"); + type.getProperties().add(property); + visitEnd(Foo2.class, type); + assertEquals("baz", definition.getParameters()[0].getName()); + assertEquals(2, type.getProperties().size()); + assertEquals(1, type.getReferences().size()); + } + + public @interface Bar { + + } + + public static class Foo { + public Foo(@Bar + String prop, @org.osoa.sca.annotations.Property(name = "foo") + String prop2) { + } + } + + public static class Foo2 { + public Foo2(@org.osoa.sca.annotations.Reference(name = "baz") + String prop1, @Bar + String prop2, @org.osoa.sca.annotations.Property(name = "foo") + String prop3) { + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java new file mode 100644 index 0000000000..a064f081d5 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/InitProcessorTestCase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.osoa.sca.annotations.Init; + +/** + * @version $Rev: 563019 $ $Date: 2007-08-05 20:43:59 -0700 (Sun, 05 Aug 2007) $ + */ +public class InitProcessorTestCase extends TestCase { + + private JavaImplementationFactory javaImplementationFactory; + + public InitProcessorTestCase() { + javaImplementationFactory = new DefaultJavaImplementationFactory(); + } + + public void testInit() throws Exception { + InitProcessor processor = new InitProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = InitProcessorTestCase.Foo.class.getMethod("init"); + processor.visitMethod(method, type); + assertNotNull(type.getInitMethod()); + } + + public void testBadInit() throws Exception { + InitProcessor processor = new InitProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = InitProcessorTestCase.Bar.class.getMethod("badInit", String.class); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalInitException e) { + // expected + } + } + + public void testTwoInit() throws Exception { + InitProcessor processor = new InitProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + Method method = InitProcessorTestCase.Bar.class.getMethod("init"); + Method method2 = InitProcessorTestCase.Bar.class.getMethod("init2"); + processor.visitMethod(method, type); + try { + processor.visitMethod(method2, type); + fail(); + } catch (DuplicateInitException e) { + // expected + } + } + + + private class Foo { + @Init + public void init() { + } + } + + + private class Bar { + @Init + public void init() { + } + + @Init + public void init2() { + } + + @Init + public void badInit(String foo) { + } + + + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaClassIntrospectorImplTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaClassIntrospectorImplTestCase.java new file mode 100644 index 0000000000..d138a03f33 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/JavaClassIntrospectorImplTestCase.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.implementation.java.introspect.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; +import org.easymock.EasyMock; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class JavaClassIntrospectorImplTestCase extends TestCase { + + public void testRegister() throws Exception { + JavaImplementationFactory factory = new DefaultJavaImplementationFactory(); + JavaClassVisitor extension = EasyMock.createNiceMock(JavaClassVisitor.class); + factory.addClassVisitor(extension); + } + + public void testUnegister() throws Exception { + JavaImplementationFactory factory = new DefaultJavaImplementationFactory(); + JavaClassVisitor extension = EasyMock.createNiceMock(JavaClassVisitor.class); + factory.addClassVisitor(extension); + factory.removeClassVisitor(extension); + } + + @SuppressWarnings("unchecked") + public void testWalk() throws Exception { + JavaImplementationFactory factory = new DefaultJavaImplementationFactory(); + JavaClassVisitor extension = EasyMock.createMock(JavaClassVisitor.class); + extension.visitClass(EasyMock.eq(Bar.class), EasyMock.isA(JavaImplementation.class)); + extension.visitConstructor(EasyMock.isA(Constructor.class), EasyMock.isA(JavaImplementation.class)); + extension.visitMethod(EasyMock.isA(Method.class), EasyMock.isA(JavaImplementation.class)); + extension.visitField(EasyMock.isA(Field.class), EasyMock.isA(JavaImplementation.class)); + extension.visitSuperClass(EasyMock.isA(Class.class), EasyMock.isA(JavaImplementation.class)); + extension.visitEnd(EasyMock.isA(Class.class), EasyMock.isA(JavaImplementation.class)); + + // mock.expects(once()).method("visitClass"); + // mock.expects(once()).method("visitMethod"); + // mock.expects(once()).method("visitField"); + // mock.expects(once()).method("visitConstructor"); + // mock.expects(once()).method("visitSuperClass"); + // mock.expects(once()).method("visitEnd"); + EasyMock.replay(extension); + factory.addClassVisitor(extension); + factory.createJavaImplementation(Bar.class); + EasyMock.verify(extension); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + private class Baz { + + } + + private class Bar extends Baz { + + protected String bar; + + public Bar() { + } + + public void bar() { + } + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java new file mode 100644 index 0000000000..044437959b --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ModelHelper.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + +/** + * @version $Rev: 563019 $ $Date: 2007-08-05 20:43:59 -0700 (Sun, 05 Aug 2007) $ + */ +public class ModelHelper { + + public static Property getProperty(JavaImplementation type, String name) { + for (Property prop : type.getProperties()) { + if (prop.getName().equals(name)) { + return prop; + } + } + return null; + } + + public static Reference getReference(JavaImplementation type, String name) { + for (Reference ref : type.getReferences()) { + if (ref.getName().equals(name)) { + return ref; + } + } + return null; + } + + public static Service getService(JavaImplementation type, String name) { + for (Service svc : type.getServices()) { + if (svc.getName().equals(name)) { + return svc; + } + } + return null; + } + + public static boolean matches(Contract contract, Class type) { + Interface interface1 = contract.getInterfaceContract().getInterface(); + if (interface1 instanceof JavaInterface) { + return type == ((JavaInterface)interface1).getJavaClass(); + } else { + return false; + } + } + + public static ComponentService createService(AssemblyFactory factory, + JavaInterfaceFactory javaFactory, Class type) { + org.apache.tuscany.sca.assembly.ComponentService ref = factory.createComponentService(); + ref.setName(type.getSimpleName()); + JavaInterface i = javaFactory.createJavaInterface(); + i.setJavaClass(type); + JavaInterfaceContract ic = javaFactory.createJavaInterfaceContract(); + ic.setInterface(i); + ref.setInterfaceContract(ic); + return ref; + } + + public static Reference createReference(AssemblyFactory factory, + JavaInterfaceFactory javaFactory, String name, Class type) { + org.apache.tuscany.sca.assembly.Reference ref = factory.createReference(); + ref.setName(name); + JavaInterface i = javaFactory.createJavaInterface(); + i.setJavaClass(type); + JavaInterfaceContract ic = javaFactory.createJavaInterfaceContract(); + ic.setInterface(i); + ref.setInterfaceContract(ic); + return ref; + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java new file mode 100644 index 0000000000..8df2b5cb16 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PolicyProcessorTestCase.java @@ -0,0 +1,418 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.ConfiguredOperation; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.OperationsConfigurator; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.impl.PolicyJavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.osoa.sca.annotations.Requires; +import org.osoa.sca.annotations.Service; + +/** + * @version $Rev: 639350 $ $Date: 2008-03-20 09:43:46 -0700 (Thu, 20 Mar 2008) $ + */ +public class PolicyProcessorTestCase extends TestCase { + private ServiceProcessor serviceProcessor; + private PolicyProcessor policyProcessor; + private PolicyJavaInterfaceVisitor visitor; + private JavaImplementation type; + + // This actually is a test for PolicyJavaInterfaceProcessor. It will get + // invoked via the call to ImplementationProcessorServiceImpl.createService in + // ServiceProcessor. Of course ServiceProcessor class has to be working. + public void stestSingleInterfaceWithIntentsOnInterfaceAtInterfaceLevel() throws Exception { + serviceProcessor.visitClass(Service1.class, type); + visitor.visitInterface((JavaInterface)type.getServices().get(0).getInterfaceContract().getInterface()); + policyProcessor.visitClass(Service1.class, type); + verifyIntents(Service1.class, type); + } + + public void stestMultipleInterfacesWithIntentsOnInterfaceAtInterfaceLevel() throws Exception { + serviceProcessor.visitClass(Service2.class, type); + visitor.visitInterface((JavaInterface)type.getServices().get(0).getInterfaceContract().getInterface()); + policyProcessor.visitClass(Service2.class, type); + verifyIntents(Service2.class, type); + } + + public void stestSingleInterfaceWithIntentsOnImplAtClassLevel() throws Exception { + serviceProcessor.visitClass(Service3.class, type); + visitor.visitInterface((JavaInterface)type.getServices().get(0).getInterfaceContract().getInterface()); + policyProcessor.visitClass(Service3.class, type); + verifyIntents(Service3.class, type); + } + + public void stestMultipleInterfacesWithIntentsOnImplAtClassLevel() throws Exception { + serviceProcessor.visitClass(Service4.class, type); + visitor.visitInterface((JavaInterface)type.getServices().get(0).getInterfaceContract().getInterface()); + policyProcessor.visitClass(Service4.class, type); + verifyIntents(Service4.class, type); + } + + public void stestSingleInterfaceWithIntentsOnInterfaceAtMethodLevel() throws Exception { + serviceProcessor.visitClass(Service5.class, type); + visitor.visitInterface((JavaInterface)type.getServices().get(0).getInterfaceContract().getInterface()); + policyProcessor.visitClass(Service5.class, type); + verifyIntents(Service5.class, type); + } + + public void testSingleInterfaceWithIntentsOnServiceAndInterfaceAtImplAndInertfaceAndMethodLevel() throws Exception { + serviceProcessor.visitClass(Service6.class, type); + visitor.visitInterface((JavaInterface)type.getServices().get(0).getInterfaceContract().getInterface()); + policyProcessor.visitClass(Service6.class, type); + for (Method method : Service6.class.getDeclaredMethods()) { + policyProcessor.visitMethod(method, type); + } + verifyIntents(Service6.class, type); + } + + private void verifyIntents(Class serviceImplClass, JavaImplementation type) { + if ( !(type instanceof PolicySetAttachPoint) ) { + fail("No Intents on the service "); + } + Requires serviceImplIntentAnnotation = (Requires)serviceImplClass.getAnnotation(Requires.class); + if (serviceImplIntentAnnotation != null) { + String[] serviceImplIntents = serviceImplIntentAnnotation.value(); + List requiredIntents = ((PolicySetAttachPoint)type).getRequiredIntents(); + if (serviceImplIntents.length > 0) { + if (requiredIntents == null || requiredIntents.size() == 0) { + fail("No Intents on the service "); + } + Map intentMap = new HashMap(); + for (Intent intent : requiredIntents) { + intentMap.put(intent.getName().getLocalPart(), intent); + } + for (String intent : serviceImplIntents) { + assertTrue("ComponentType for Service class " + serviceImplClass.getName() + + " did not contain Service Implementation intent " + + intent, intentMap.containsKey(intent)); + } + } + } + + // This should match what was specified on @Service for a Service Implementation + // If we use these to get the Service names and we get a null Service + // name then it would seem that wrong values were put on the @Service annotation + // or the wrong interfaces were specified on the implements list of the class + // statement? + Map serviceMap = new HashMap(); + for (org.apache.tuscany.sca.assembly.Service service: type.getServices()) { + serviceMap.put(service.getName(), service); + } + for (Class interfaceClass : serviceImplClass.getInterfaces()) { + Requires interfaceIntentAnnotation = (Requires)interfaceClass.getAnnotation(Requires.class); + org.apache.tuscany.sca.assembly.Service service = serviceMap.get(interfaceClass.getSimpleName()); + if (service == null) { + fail("No service defined for interface " + interfaceClass.getSimpleName() + + " on Service Implementation " + + serviceImplClass.getName()); + } + + if (interfaceIntentAnnotation != null) { + String[] interfaceIntents = interfaceIntentAnnotation.value(); + List requiredIntents = service.getInterfaceContract().getInterface().getRequiredIntents(); + if (interfaceIntents.length > 0) { + if (requiredIntents == null || requiredIntents.size() == 0) { + fail("No Intents on the service " + service.getName()); + } + Map intentMap = new HashMap(); + for (Intent intent : requiredIntents) { + intentMap.put(intent.getName().getLocalPart(), intent); + } + for (String intent : interfaceIntents) { + assertTrue("Interface " + service.getName() + + " did not contain Service Interface intent " + + intent, intentMap.containsKey(intent)); + } + } + } + + for (Method method : interfaceClass.getDeclaredMethods()) { + Requires methodIntentAnnotation = method.getAnnotation(Requires.class); + + // Verify that each of the Intents on each of the Service + // Interface Methods exist on their associated operation. + if (methodIntentAnnotation != null) { + String[] methodIntents = methodIntentAnnotation.value(); + if (methodIntents.length > 0) { + List requiredIntents = null; + for ( ConfiguredOperation confOp : service.getConfiguredOperations() ) { + if ( confOp.getName().equals(method.getName()) && + confOp.getContractName().equals(service.getName()) ) { + requiredIntents = confOp.getRequiredIntents(); + } + } + + if (requiredIntents == null || requiredIntents.size() == 0) { + fail("No Intents on operation " + method.getName()); + } + for (String intent : methodIntents) { + boolean found = false; + for (Intent requiredIntent: requiredIntents) { + if (requiredIntent.getName().getLocalPart().equals(intent)) { + found = true; + break; + } + } + assertTrue("Operation " + method.getName() + + " did not contain Service Interface method intent " + + intent, found); + } + } + } + } + + for (Method method : serviceImplClass.getDeclaredMethods()) { + Requires methodIntentAnnotation = method.getAnnotation(Requires.class); + + // Verify that each of the Intents on each of the Service + // Implementation Methods exist on their associated + // operation. + if (methodIntentAnnotation != null) { + String[] methodIntents = methodIntentAnnotation.value(); + if (methodIntents.length > 0) { + List requiredIntents = null; + for ( ConfiguredOperation confOp : ((OperationsConfigurator)type).getConfiguredOperations() ) { + if ( confOp.getName().equals(method.getName()) ) { + requiredIntents = confOp.getRequiredIntents(); + } + } + + if (requiredIntents == null || requiredIntents.size() == 0) { + fail("No Intents on operation " + method.getName()); + } + + for (String intent : methodIntents) { + boolean found = false; + for (Intent requiredIntent: requiredIntents) { + if (requiredIntent.getName().getLocalPart().equals(intent)) { + found = true; + break; + } + } + assertTrue("Operation " + method.getName() + + " did not contain Implementation method intent " + + intent, found); + } + } + } + } + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + serviceProcessor = new ServiceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory()); + policyProcessor = new PolicyProcessor(new DefaultAssemblyFactory(), new DefaultPolicyFactory()); + visitor = new PolicyJavaInterfaceVisitor(new DefaultPolicyFactory()); + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + type = javaImplementationFactory.createJavaImplementation(); + } + + // @Remotable + @Requires( {"transaction.global"}) + private interface Interface1 { + int method1(); + + int method2(); + + int method3(); + + int method4(); + } + + @Service(Interface1.class) + private class Service1 implements Interface1 { + public int method1() { + return 0; + } + + public int method2() { + return 0; + } + + public int method3() { + return 0; + } + + public int method4() { + return 0; + } + } + + // @Remotable + @Requires( {"transaction.local"}) + private interface Interface2 { + int method5(); + + int method6(); + } + + @Service(interfaces = {Interface1.class, Interface2.class}) + private class Service2 implements Interface1, Interface2 { + public int method1() { + return 0; + } + + public int method2() { + return 0; + } + + public int method3() { + return 0; + } + + public int method4() { + return 0; + } + + public int method5() { + return 0; + } + + public int method6() { + return 0; + } + } + + // @Remotable + private interface Interface3 { + int method1(); + + int method2(); + + int method3(); + + int method4(); + } + + @Service(Interface3.class) + @Requires( {"transaction.global"}) + private class Service3 implements Interface3 { + public int method1() { + return 0; + } + + public int method2() { + return 0; + } + + public int method3() { + return 0; + } + + public int method4() { + return 0; + } + } + + // @Remotable + private interface Interface4 { + int method5(); + + int method6(); + } + + @Service(interfaces = {Interface3.class, Interface4.class}) + @Requires( {"transaction.local"}) + private class Service4 implements Interface3, Interface4 { + public int method1() { + return 0; + } + + public int method2() { + return 0; + } + + public int method3() { + return 0; + } + + public int method4() { + return 0; + } + + public int method5() { + return 0; + } + + public int method6() { + return 0; + } + } + + private interface Interface5 { + @Requires( {"transaction.global"}) + int method1(); + + @Requires( {"transaction.local"}) + int method2(); + } + + @Service(Interface5.class) + private class Service5 implements Interface5 { + public int method1() { + return 0; + } + + public int method2() { + return 0; + } + } + + @Requires( {"transaction.global.Interface6"}) + private interface Interface6 { + @Requires( {"transaction.global.Interface6.method1"}) + int method1(); + + @Requires( {"transaction.local.Interface6.method2"}) + int method2(); + } + + @Service(Interface6.class) + @Requires( {"transaction.global.Service6"}) + private class Service6 implements Interface6 { + @Requires( {"transaction.global.Service6.method1"}) + public int method1() { + return 0; + } + + @Requires( {"transaction.global.Service6.method1"}) + public int method2() { + return 0; + } + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java new file mode 100644 index 0000000000..47ca01a63a --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/PropertyProcessorTestCase.java @@ -0,0 +1,212 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getProperty; + +import java.util.Collection; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.osoa.sca.annotations.Property; + +/** + * @version $Rev: 584985 $ $Date: 2007-10-15 17:47:36 -0700 (Mon, 15 Oct 2007) $ + */ +public class PropertyProcessorTestCase extends TestCase { + + JavaImplementation type; + PropertyProcessor processor; + + public void testMethodAnnotation() throws Exception { + processor.visitMethod(Foo.class.getMethod("setFoo", String.class), type); + assertNotNull(getProperty(type, "foo")); + } + + public void testMethodRequired() throws Exception { + processor.visitMethod(Foo.class.getMethod("setFooRequired", String.class), type); + org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "fooRequired"); + assertNotNull(prop); + assertTrue(prop.isMustSupply()); + } + + public void testMethodName() throws Exception { + processor.visitMethod(Foo.class.getMethod("setBarMethod", String.class), type); + assertNotNull(getProperty(type, "bar")); + } + + public void testFieldAnnotation() throws Exception { + processor.visitField(Foo.class.getDeclaredField("baz"), type); + assertNotNull(getProperty(type, "baz")); + } + + public void testFieldRequired() throws Exception { + processor.visitField(Foo.class.getDeclaredField("bazRequired"), type); + org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "bazRequired"); + assertNotNull(prop); + assertTrue(prop.isMustSupply()); + } + + public void testFieldName() throws Exception { + processor.visitField(Foo.class.getDeclaredField("bazField"), type); + assertNotNull(getProperty(type, "theBaz")); + } + + public void testDuplicateFields() throws Exception { + processor.visitField(Bar.class.getDeclaredField("dup"), type); + try { + processor.visitField(Bar.class.getDeclaredField("baz"), type); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testDuplicateMethods() throws Exception { + processor.visitMethod(Bar.class.getMethod("setDupMethod", String.class), type); + try { + processor.visitMethod(Bar.class.getMethod("setDupSomeMethod", String.class), type); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testInvalidProperty() throws Exception { + try { + processor.visitMethod(Bar.class.getMethod("badMethod"), type); + fail(); + } catch (IllegalPropertyException e) { + // expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + type = javaImplementationFactory.createJavaImplementation(); + processor = new PropertyProcessor(new DefaultAssemblyFactory()); + } + + private class Foo { + + @Property + protected String baz; + @Property(required = true) + protected String bazRequired; + @Property(name = "theBaz") + protected String bazField; + + @Property + public void setFoo(String string) { + } + + @Property(required = true) + public void setFooRequired(String string) { + } + + @Property(name = "bar") + public void setBarMethod(String string) { + } + + } + + private class Bar { + + @Property + protected String dup; + + @Property(name = "dup") + protected String baz; + + @Property + public void setDupMethod(String s) { + } + + @Property(name = "dupMethod") + public void setDupSomeMethod(String s) { + } + + @Property + public void badMethod() { + } + + } + + private class Multiple { + @Property + protected List refs1; + + @Property + protected String[] refs2; + + @Property + public void setRefs3(String[] refs) { + } + + @Property + public void setRefs4(Collection refs) { + } + + } + + private Class getBaseType(JavaElementImpl element) { + return JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + } + + public void testMultiplicityCollection() throws Exception { + processor.visitField(Multiple.class.getDeclaredField("refs1"), type); + org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs1"); + assertNotNull(prop); + assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName()))); + assertTrue(prop.isMany()); + } + + public void testMultiplicityArray() throws Exception { + processor.visitField(Multiple.class.getDeclaredField("refs2"), type); + org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs2"); + assertNotNull(prop); + assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName()))); + assertTrue(prop.isMany()); + } + + public void testMultiplicityArrayMethod() throws Exception { + processor.visitMethod(Multiple.class.getMethod("setRefs3", String[].class), type); + org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs3"); + assertNotNull(prop); + assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName()))); + assertTrue(prop.isMany()); + } + + public void testMultiplicityCollectionMethod() throws Exception { + processor.visitMethod(Multiple.class.getMethod("setRefs4", Collection.class), type); + org.apache.tuscany.sca.assembly.Property prop = getProperty(type, "refs4"); + assertNotNull(prop); + assertSame(String.class, getBaseType(type.getPropertyMembers().get(prop.getName()))); + assertTrue(prop.isMany()); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java new file mode 100644 index 0000000000..91a3d7e7e4 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ReferenceProcessorTestCase.java @@ -0,0 +1,221 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getReference; + +import java.util.Collection; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.osoa.sca.annotations.Reference; + +/** + * @version $Rev: 584985 $ $Date: 2007-10-15 17:47:36 -0700 (Mon, 15 Oct 2007) $ + */ +public class ReferenceProcessorTestCase extends TestCase { + + private JavaImplementation type; + private ReferenceProcessor processor; + + public void testMethodAnnotation() throws Exception { + processor.visitMethod(ReferenceProcessorTestCase.Foo.class.getMethod("setFoo", Ref.class), type); + org.apache.tuscany.sca.assembly.Reference reference = getReference(type, "foo"); + assertNotNull(reference); + assertEquals(Ref.class, ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass()); + } + + public void testMethodRequired() throws Exception { + processor.visitMethod(ReferenceProcessorTestCase.Foo.class.getMethod("setFooRequired", Ref.class), type); + org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "fooRequired"); + assertNotNull(ref); + assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity()); + } + + public void testMethodName() throws Exception { + processor.visitMethod(ReferenceProcessorTestCase.Foo.class.getMethod("setBarMethod", Ref.class), type); + assertNotNull(getReference(type, "bar")); + } + + public void testFieldAnnotation() throws Exception { + processor.visitField(ReferenceProcessorTestCase.Foo.class.getDeclaredField("baz"), type); + org.apache.tuscany.sca.assembly.Reference reference = getReference(type, "baz"); + assertNotNull(reference); + assertEquals(Ref.class, ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass()); + } + + public void testFieldRequired() throws Exception { + processor.visitField(ReferenceProcessorTestCase.Foo.class.getDeclaredField("bazRequired"), type); + org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "bazRequired"); + assertNotNull(ref); + assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity()); + } + + public void testFieldName() throws Exception { + processor.visitField(ReferenceProcessorTestCase.Foo.class.getDeclaredField("bazField"), type); + assertNotNull(getReference(type, "theBaz")); + } + + public void testDuplicateFields() throws Exception { + processor.visitField(ReferenceProcessorTestCase.Bar.class.getDeclaredField("dup"), type); + try { + processor.visitField(ReferenceProcessorTestCase.Bar.class.getDeclaredField("baz"), type); + fail(); + } catch (DuplicateReferenceException e) { + // expected + } + } + + public void testDuplicateMethods() throws Exception { + processor.visitMethod(ReferenceProcessorTestCase.Bar.class.getMethod("setDupMethod", Ref.class), type); + try { + processor.visitMethod(ReferenceProcessorTestCase.Bar.class.getMethod("setDupSomeMethod", Ref.class), type); + fail(); + } catch (DuplicateReferenceException e) { + // expected + } + } + + public void testInvalidProperty() throws Exception { + try { + processor.visitMethod(ReferenceProcessorTestCase.Bar.class.getMethod("badMethod"), type); + fail(); + } catch (IllegalReferenceException e) { + // expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + type = javaImplementationFactory.createJavaImplementation(); + processor = new ReferenceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory()); + } + + private interface Ref { + } + + private class Foo { + + @Reference + protected Ref baz; + @Reference(required = true) + protected Ref bazRequired; + @Reference(name = "theBaz") + protected Ref bazField; + + @Reference + public void setFoo(Ref ref) { + } + + @Reference(required = true) + public void setFooRequired(Ref ref) { + } + + @Reference(name = "bar") + public void setBarMethod(Ref ref) { + } + + } + + private class Bar { + + @Reference + protected Ref dup; + + @Reference(name = "dup") + protected Ref baz; + + @Reference + public void setDupMethod(Ref s) { + } + + @Reference(name = "dupMethod") + public void setDupSomeMethod(Ref s) { + } + + @Reference + public void badMethod() { + } + + } + + private class Multiple { + @Reference(required = true) + protected List refs1; + + @Reference(required = false) + protected Ref[] refs2; + + @Reference(required = true) + public void setRefs3(Ref[] refs) { + } + + @Reference(required = false) + public void setRefs4(Collection refs) { + } + + } + + public void testMultiplicity1ToN() throws Exception { + processor.visitField(Multiple.class.getDeclaredField("refs1"), type); + org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs1"); + assertNotNull(ref); + assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass()); + assertEquals(Multiplicity.ONE_N, ref.getMultiplicity()); + // assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity()); + } + + public void testMultiplicityTo0ToN() throws Exception { + processor.visitField(Multiple.class.getDeclaredField("refs2"), type); + org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs2"); + assertNotNull(ref); + assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass()); + assertEquals(Multiplicity.ZERO_N, ref.getMultiplicity()); + // assertFalse(ref.isMustSupply()); + } + + public void testMultiplicity1ToNMethod() throws Exception { + processor.visitMethod(Multiple.class.getMethod("setRefs3", Ref[].class), type); + org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs3"); + assertNotNull(ref); + assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass()); + assertEquals(Multiplicity.ONE_N, ref.getMultiplicity()); + // assertEquals(Multiplicity.ONE_ONE, ref.getMultiplicity()); + } + + public void testMultiplicity0ToNMethod() throws Exception { + processor.visitMethod(Multiple.class.getMethod("setRefs4", Collection.class), type); + org.apache.tuscany.sca.assembly.Reference ref = getReference(type, "refs4"); + assertNotNull(ref); + assertSame(Ref.class, ((JavaInterface)ref.getInterfaceContract().getInterface()).getJavaClass()); + assertEquals(Multiplicity.ZERO_N, ref.getMultiplicity()); + // assertFalse(ref.isMustSupply()); + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java new file mode 100644 index 0000000000..02bebca8eb --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ResourceProcessorTestCase.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaResourceImpl; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ResourceProcessorTestCase extends TestCase { + + JavaImplementation type; + ResourceProcessor processor = new ResourceProcessor(new DefaultAssemblyFactory()); + + public void testVisitField() throws Exception { + Field field = Foo.class.getDeclaredField("bar"); + processor.visitField(field, type); + JavaResourceImpl resource = type.getResources().get("bar"); + assertFalse(resource.isOptional()); + assertNull(resource.getMappedName()); + assertEquals(field.getType(), resource.getElement().getType()); + } + + public void testVisitMethod() throws Exception { + Method method = Foo.class.getMethod("setBar", Bar.class); + processor.visitMethod(method, type); + JavaResourceImpl resource = type.getResources().get("bar"); + assertFalse(resource.isOptional()); + assertNull(resource.getMappedName()); + assertEquals(method.getParameterTypes()[0], resource.getElement().getType()); + } + + public void testVisitNamedMethod() throws Exception { + Method method = Foo.class.getMethod("setBar2", Bar.class); + processor.visitMethod(method, type); + JavaResourceImpl resource = type.getResources().get("someName"); + assertFalse(resource.isOptional()); + assertEquals("mapped", resource.getMappedName()); + } + + public void testVisitBadMethod() throws Exception { + Method method = Foo.class.getMethod("setBad"); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalResourceException e) { + // expected + } + } + + public void testDuplicateResources() throws Exception { + Field field = Foo.class.getDeclaredField("bar"); + processor.visitField(field, type); + try { + processor.visitField(field, type); + fail(); + } catch (DuplicateResourceException e) { + //expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + type = javaImplementationFactory.createJavaImplementation(); + } + + private class Foo { + + @org.apache.tuscany.sca.implementation.java.introspect.impl.Resource + protected Bar bar; + + @org.apache.tuscany.sca.implementation.java.introspect.impl.Resource(optional = true) + protected Bar barNotRequired; + + @org.apache.tuscany.sca.implementation.java.introspect.impl.Resource + public void setBar(Bar bar) { + } + + @org.apache.tuscany.sca.implementation.java.introspect.impl.Resource(name = "someName", mappedName = "mapped") + public void setBar2(Bar bar) { + } + + @org.apache.tuscany.sca.implementation.java.introspect.impl.Resource + public void setBad() { + } + + } + + private interface Bar { + + } +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java new file mode 100644 index 0000000000..63a02614fc --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ScopeProcessorTestCase.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.impl.JavaScopeImpl; +import org.easymock.EasyMock; + +/** + * @version $Rev: 567542 $ $Date: 2007-08-19 22:13:29 -0700 (Sun, 19 Aug 2007) $ + */ +public class ScopeProcessorTestCase extends TestCase { + + Component parent; + private JavaImplementationFactory javaImplementationFactory; + + public void testCompositeScope() throws IntrospectionException { + ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + + processor.visitClass(Composite.class, type); + assertEquals(JavaScopeImpl.COMPOSITE, type.getJavaScope()); + } + + public void testSessionScope() throws IntrospectionException { + ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(Session.class, type); + assertEquals(JavaScopeImpl.SESSION, type.getJavaScope()); + } + + public void testConversationalScope() throws IntrospectionException { + ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(Conversation.class, type); + assertEquals(JavaScopeImpl.CONVERSATION, type.getJavaScope()); + } + + public void testRequestScope() throws IntrospectionException { + ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(Request.class, type); + assertEquals(JavaScopeImpl.REQUEST, type.getJavaScope()); + } + + public void testStatelessScope() throws IntrospectionException { + ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(Stateless.class, type); + assertEquals(JavaScopeImpl.STATELESS, type.getJavaScope()); + } + + public void testNoScope() throws IntrospectionException { + ScopeProcessor processor = new ScopeProcessor(new DefaultAssemblyFactory()); + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(None.class, type); + assertEquals(JavaScopeImpl.STATELESS, type.getJavaScope()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + parent = EasyMock.createNiceMock(Component.class); + } + + @org.osoa.sca.annotations.Scope("COMPOSITE") + private class Composite { + } + + @org.osoa.sca.annotations.Scope("SESSION") + private class Session { + } + + @org.osoa.sca.annotations.Scope("CONVERSATION") + private class Conversation { + } + + @org.osoa.sca.annotations.Scope("REQUEST") + private class Request { + } + + @org.osoa.sca.annotations.Scope("STATELESS") + private class Stateless { + } + + private class None { + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java new file mode 100644 index 0000000000..9e3db807ba --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceCallbackTestCase.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import static org.apache.tuscany.sca.implementation.java.introspect.impl.ModelHelper.getService; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.interfacedef.InvalidCallbackException; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.osoa.sca.CallableReference; +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Service; + +/** + * @version $Rev: 571266 $ $Date: 2007-08-30 11:23:58 -0700 (Thu, 30 Aug 2007) $ + */ +public class ServiceCallbackTestCase extends TestCase { + private ServiceProcessor processor; + private JavaImplementationFactory javaImplementationFactory; + + @Override + protected void setUp() throws Exception { + processor = new ServiceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory()); + javaImplementationFactory = new DefaultJavaImplementationFactory(); + } + + public void testMethodCallbackInterface() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(FooImpl.class, type); + org.apache.tuscany.sca.assembly.Service service = getService(type, Foo.class.getSimpleName()); + assertNotNull(service); + Method method = FooImpl.class.getMethod("setCallback", FooCallback.class); + processor.visitMethod(method, type); + assertEquals(method, type.getCallbackMembers().get(FooCallback.class.getName()).getAnchor()); + } + + public void testFieldCallbackInterface() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(FooImpl.class, type); + org.apache.tuscany.sca.assembly.Service service = getService(type, Foo.class.getSimpleName()); + assertNotNull(service); + Field field = FooImpl.class.getDeclaredField("callback"); + processor.visitField(field, type); + assertEquals(field, type.getCallbackMembers().get(FooCallback.class.getName()).getAnchor()); + } + + public void testFieldCallbackInterface1() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(FooImpl1.class, type); + org.apache.tuscany.sca.assembly.Service service = getService(type, Foo.class.getSimpleName()); + assertNotNull(service); + Field field1 = FooImpl1.class.getDeclaredField("callbackRef"); + processor.visitField(field1, type); + assertEquals(field1, type.getCallbackMembers().get(FooCallback.class.getName()).getAnchor()); + + } + + public void testMethodDoesNotMatchCallback() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(BadBarImpl.class, type); + Method method = BadBarImpl.class.getMethod("setWrongInterfaceCallback", String.class); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalCallbackReferenceException e) { + // expected + } + } + + public void testNoParamCallback() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(BadBarImpl.class, type); + Method method = BadBarImpl.class.getMethod("setNoParamCallback"); + try { + processor.visitMethod(method, type); + fail(); + } catch (IllegalCallbackReferenceException e) { + // expected + } + } + + public void testFieldDoesNotMatchCallback() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + processor.visitClass(BadBarImpl.class, type); + Field field = BadBarImpl.class.getDeclaredField("wrongInterfaceCallback"); + try { + processor.visitField(field, type); + fail(); + } catch (IllegalCallbackReferenceException e) { + // expected + } + } + + public void testBadCallbackInterfaceAnnotation() throws Exception { + JavaImplementation type = javaImplementationFactory.createJavaImplementation(); + try { + processor.visitClass(BadFooImpl.class, type); + fail(); + } catch (IntrospectionException e) { + // expected + assertTrue(e.getCause() instanceof InvalidCallbackException); + } + } + + @Callback(FooCallback.class) + private interface Foo { + + } + + private interface FooCallback { + + } + + @Service(Foo.class) + private static class FooImpl implements Foo { + + @Callback + protected FooCallback callback; + + @Callback + public void setCallback(FooCallback cb) { + + } + } + + @Service(Foo.class) + private static class FooImpl1 implements Foo { + @Callback + protected CallableReference callbackRef; + } + + private static class BadBarImpl implements Foo { + @Callback + protected String wrongInterfaceCallback; + + @Callback + public void setWrongInterfaceCallback(String cb) { + + } + + @Callback + public void setNoParamCallback() { + + } + + } + + @Callback + private interface BadFoo { + + } + + @Service(BadFoo.class) + private static class BadFooImpl implements BadFoo { + + } + +} diff --git a/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java new file mode 100644 index 0000000000..1ffae27129 --- /dev/null +++ b/branches/sca-android/tuscany-implementation-java/src/test/java/org/apache/tuscany/sca/implementation/java/introspect/impl/ServiceProcessorTestCase.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.introspect.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFactory; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Service; + +/** + * @version $Rev: 575401 $ $Date: 2007-09-13 11:54:15 -0700 (Thu, 13 Sep 2007) $ + */ +public class ServiceProcessorTestCase extends TestCase { + private ServiceProcessor processor; + private JavaImplementation type; + + public void testMultipleInterfaces() throws Exception { + processor.visitClass(FooMultiple.class, type); + assertEquals(2, type.getServices().size()); + org.apache.tuscany.sca.assembly.Service service = ModelHelper.getService(type, Baz.class.getSimpleName()); + assertEquals(Baz.class, ((JavaInterface)service.getInterfaceContract().getInterface()).getJavaClass()); + assertEquals(Bar.class, ((JavaInterface)service.getInterfaceContract().getCallbackInterface()).getJavaClass()); + assertNotNull(ModelHelper.getService(type, Bar.class.getSimpleName())); + } + + public void testSingleInterfaces() throws Exception { + processor.visitClass(FooSingle.class, type); + assertEquals(1, type.getServices().size()); + assertNotNull(ModelHelper.getService(type, Baz.class.getSimpleName())); + } + + public void testMultipleNoService() throws Exception { + processor.visitClass(FooMultipleNoService.class, type); + assertEquals(0, type.getServices().size()); + } + + /** + * Verifies a service with a callback annotation is recognized + */ + public void testMultipleWithCallbackAnnotation() throws Exception { + processor.visitClass(FooMultipleWithCalback.class, type); + assertEquals(1, type.getServices().size()); + } + + public void testRemotableNoService() throws Exception { + processor.visitClass(FooRemotableNoService.class, type); + assertEquals(1, type.getServices().size()); + org.apache.tuscany.sca.assembly.Service service = ModelHelper.getService(type, BazRemotable.class.getSimpleName()); + assertEquals(BazRemotable.class, ((JavaInterface)service.getInterfaceContract().getInterface()).getJavaClass()); + } + + public void testNonInterface() throws Exception { + processor.visitClass(FooServiceUsingClassImpl.class, type); + } + + public void testNoInterfaces() throws Exception { + try { + processor.visitClass(BadDefinition.class, type); + fail(); + } catch (IllegalServiceDefinitionException e) { + //expected + } + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + processor = new ServiceProcessor(new DefaultAssemblyFactory(), new DefaultJavaInterfaceFactory()); + JavaImplementationFactory javaImplementationFactory = new DefaultJavaImplementationFactory(); + type = javaImplementationFactory.createJavaImplementation(); + } + + @Callback(Bar.class) + private interface Baz { + } + + private interface Bar { + } + + private interface Bar2 { + } + + @Remotable + private interface BazRemotable { + } + + @Service(interfaces = {Baz.class, Bar.class}) + private class FooMultiple implements Baz, Bar { + + } + + @Service(Baz.class) + private class FooSingle implements Baz, Bar { + + } + + private class FooMultipleNoService implements Bar, Bar2 { + + } + + private class FooMultipleWithCalback implements Baz, Bar { + + } + + private class FooRemotableNoService implements BazRemotable, Bar { + + } + + @Service(FooSingle.class) + private class FooServiceUsingClassImpl extends FooSingle { + + } + + + @Service() + private class BadDefinition extends FooSingle { + + } + +} diff --git a/branches/sca-android/tuscany-policy-xml/.classpath b/branches/sca-android/tuscany-policy-xml/.classpath new file mode 100644 index 0000000000..d4a80d05ca --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/.classpath @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-policy-xml/.project b/branches/sca-android/tuscany-policy-xml/.project new file mode 100644 index 0000000000..effe3b2ca5 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/.project @@ -0,0 +1,20 @@ + + tuscany-policy-xml + Parent POM defining settings that can be used across Tuscany + + tuscany-contribution + tuscany-assembly + tuscany-policy + tuscany-extensibility + tuscany-interface + tuscany-definitions + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/branches/sca-android/tuscany-policy-xml/.settings/org.eclipse.jdt.core.prefs b/branches/sca-android/tuscany-policy-xml/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..0c759c0227 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Thu Mar 20 19:19:35 PDT 2008 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 diff --git a/branches/sca-android/tuscany-policy-xml/DISCLAIMER b/branches/sca-android/tuscany-policy-xml/DISCLAIMER new file mode 100644 index 0000000000..d68a410903 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/DISCLAIMER @@ -0,0 +1,8 @@ +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + diff --git a/branches/sca-android/tuscany-policy-xml/LICENSE b/branches/sca-android/tuscany-policy-xml/LICENSE new file mode 100644 index 0000000000..6e529a25c4 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/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/branches/sca-android/tuscany-policy-xml/NOTICE b/branches/sca-android/tuscany-policy-xml/NOTICE new file mode 100644 index 0000000000..1325efd8bf --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/tuscany-policy-xml/pom.xml b/branches/sca-android/tuscany-policy-xml/pom.xml new file mode 100644 index 0000000000..8373592b49 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/pom.xml @@ -0,0 +1,120 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-incubating-SNAPSHOT + ../pom.xml + + tuscany-policy-xml + Apache Tuscany SCA Policy XML Model + + + + org.apache.tuscany.sca + tuscany-policy + 2.0-incubating-SNAPSHOT + + + + org.apache.tuscany.sca + tuscany-contribution + 2.0-incubating-SNAPSHOT + + + + org.apache.ws.commons.axiom + axiom-api + 1.2.5 + + + xerces + xercesImpl + + + javax.mail + mail + + + commons-logging + commons-logging + + + + + + xerces + xercesImpl + 2.8.1 + runtime + + + + org.apache.neethi + neethi + 2.0.2 + + + wsdl4j + wsdl4j + + + org.codehaus.woodstox + wstx-asl + + + + + + org.apache.ws.commons.axiom + axiom-impl + 1.2.5 + runtime + + + javax.mail + mail + + + + + + org.codehaus.woodstox + wstx-asl + 3.2.1 + runtime + + + + commons-logging + commons-logging + 1.1 + runtime + + + commons-logging + commons-logging + + + + + diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/BindingTypeProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/BindingTypeProcessor.java new file mode 100644 index 0000000000..b54adf492b --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/BindingTypeProcessor.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.policy.xml; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.impl.BindingTypeImpl; + + +/** + * Processor for handling XML models of BindingType meta data definitions + */ +public class BindingTypeProcessor extends IntentAttachPointTypeProcessor { + + public BindingTypeProcessor(PolicyFactory policyFactory, IntentAttachPointTypeFactory intentAttachPointTypeFactory, StAXArtifactProcessor extensionProcessor) { + super(policyFactory, intentAttachPointTypeFactory, extensionProcessor); + } + + public QName getArtifactType() { + return BINDING_TYPE_QNAME; + } + + @Override + protected IntentAttachPointType resolveExtensionType(IntentAttachPointType extnType, ModelResolver resolver) throws ContributionResolveException { + if ( extnType instanceof BindingTypeImpl ) { + BindingTypeImpl bindingType = (BindingTypeImpl)extnType; + return resolver.resolveModel(BindingTypeImpl.class, bindingType); + } else { + return extnType; + } + + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ImplementationTypeProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ImplementationTypeProcessor.java new file mode 100644 index 0000000000..e588f93663 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ImplementationTypeProcessor.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.policy.xml; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.impl.ImplementationTypeImpl; + + +/** + * Processor for handling XML models of ImplementationType meta data definitions + */ +public class ImplementationTypeProcessor extends IntentAttachPointTypeProcessor { + + public ImplementationTypeProcessor(PolicyFactory policyFactory, IntentAttachPointTypeFactory intentAttachPointTypeFactory, StAXArtifactProcessor extensionProcessor) { + super(policyFactory, intentAttachPointTypeFactory, extensionProcessor); + } + + public QName getArtifactType() { + return IMPLEMENTATION_TYPE_QNAME; + } + + @Override + protected IntentAttachPointType resolveExtensionType(IntentAttachPointType extnType, ModelResolver resolver) throws ContributionResolveException { + if ( extnType instanceof ImplementationTypeImpl ) { + ImplementationTypeImpl implType = (ImplementationTypeImpl)extnType; + return resolver.resolveModel(ImplementationTypeImpl.class, implType); + } else { + return extnType; + } + + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentAttachPointTypeProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentAttachPointTypeProcessor.java new file mode 100644 index 0000000000..a69e3aca3a --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentAttachPointTypeProcessor.java @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.policy.xml; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +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.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.impl.BindingTypeImpl; +import org.apache.tuscany.sca.policy.impl.ImplementationTypeImpl; + + +/** + * Processor for handling XML models of ExtensionType meta data definitions + */ +public abstract class IntentAttachPointTypeProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor, PolicyConstants { + + private IntentAttachPointTypeFactory attachPointTypeFactory; + private PolicyFactory policyFactory; + + protected abstract IntentAttachPointType resolveExtensionType(IntentAttachPointType extnType, ModelResolver resolver) throws ContributionResolveException; + + public IntentAttachPointTypeProcessor(PolicyFactory policyFactory, IntentAttachPointTypeFactory attachPointTypeFactory, StAXArtifactProcessor extensionProcessor) { + this.policyFactory = policyFactory; + this.attachPointTypeFactory = attachPointTypeFactory; + } + + public IntentAttachPointType read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + QName type = getQName(reader, TYPE); + + if ( type != null ) { + if ( type.getLocalPart().startsWith(BINDING) ) { + IntentAttachPointType bindingType = attachPointTypeFactory.createBindingType(); + bindingType.setName(type); + bindingType.setUnresolved(true); + + readAlwaysProvidedIntents(bindingType, reader); + readMayProvideIntents(bindingType, reader); + return bindingType; + } else if ( type.getLocalPart().startsWith(IMPLEMENTATION) ) { + IntentAttachPointType implType = attachPointTypeFactory.createImplementationType(); + implType.setName(type); + implType.setUnresolved(true); + + readAlwaysProvidedIntents(implType, reader); + readMayProvideIntents(implType, reader); + return implType; + } else { + throw new ContributionReadException("Unrecognized IntentAttachPointType - " + type); + } + } else { + throw new ContributionReadException("Required attribute '" + TYPE + + "' missing from BindingType Definition"); + } + } + + private void readAlwaysProvidedIntents(IntentAttachPointType extnType, XMLStreamReader reader) { + String value = reader.getAttributeValue(null, ALWAYS_PROVIDES); + if (value != null) { + List alwaysProvided = extnType.getAlwaysProvidedIntents(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + Intent intent = policyFactory.createIntent(); + intent.setName(qname); + alwaysProvided.add(intent); + } + } + } + + private void readMayProvideIntents(IntentAttachPointType extnType, XMLStreamReader reader) { + String value = reader.getAttributeValue(null, MAY_PROVIDE); + if (value != null) { + List mayProvide = extnType.getMayProvideIntents(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + Intent intent = policyFactory.createIntent(); + intent.setName(qname); + mayProvide.add(intent); + } + } + } + + public void write(IntentAttachPointType extnType, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + // Write an + if ( extnType instanceof BindingTypeImpl ) { + writer.writeStartElement(SCA10_NS, BINDING_TYPE); + } else if ( extnType instanceof ImplementationTypeImpl ) { + writer.writeStartElement(SCA10_NS, IMPLEMENTATION_TYPE); + } + + writeAlwaysProvidesIntentsAttribute(extnType, writer); + writeMayProvideIntentsAttribute(extnType, writer); + + writer.writeEndElement(); + } + + private void writeMayProvideIntentsAttribute(IntentAttachPointType extnType, XMLStreamWriter writer) throws XMLStreamException { + StringBuffer sb = new StringBuffer(); + for ( Intent intent : extnType.getMayProvideIntents() ) { + writer.writeNamespace(intent.getName().getPrefix(), intent.getName().getNamespaceURI()); + sb.append(intent.getName().getPrefix() + COLON + intent.getName().getLocalPart()); + sb.append(WHITE_SPACE); + } + + if ( sb.length() > 0 ) { + writer.writeAttribute(MAY_PROVIDE, sb.toString()); + } + } + + private void writeAlwaysProvidesIntentsAttribute(IntentAttachPointType extnType, XMLStreamWriter writer) throws XMLStreamException { + StringBuffer sb = new StringBuffer(); + for ( Intent intent : extnType.getAlwaysProvidedIntents() ) { + writer.writeNamespace(intent.getName().getPrefix(), intent.getName().getNamespaceURI()); + sb.append(intent.getName().getPrefix() + COLON + intent.getName().getLocalPart()); + sb.append(WHITE_SPACE); + } + + if ( sb.length() > 0 ) { + writer.writeAttribute(ALWAYS_PROVIDES, sb.toString()); + + } + } + + public void resolve(IntentAttachPointType extnType, ModelResolver resolver) throws ContributionResolveException { + resolveAlwaysProvidedIntents(extnType, resolver); + resolveMayProvideIntents(extnType, resolver); + extnType.setUnresolved(false); + //resolveExtensionType(extnType, resolver); + } + + private void resolveAlwaysProvidedIntents(IntentAttachPointType extensionType, + ModelResolver resolver) throws ContributionResolveException { + if (extensionType != null) { + // resolve all provided intents + List alwaysProvided = new ArrayList(); + for (Intent providedIntent : extensionType.getAlwaysProvidedIntents()) { + if (providedIntent.isUnresolved()) { + providedIntent = resolver.resolveModel(Intent.class, providedIntent); + if (!providedIntent.isUnresolved()) { + alwaysProvided.add(providedIntent); + } else { + throw new ContributionResolveException( + "Always Provided Intent - " + providedIntent + + " not found for ExtensionType " + + extensionType); + + } + } else { + alwaysProvided.add(providedIntent); + } + } + extensionType.getAlwaysProvidedIntents().clear(); + extensionType.getAlwaysProvidedIntents().addAll(alwaysProvided); + } + } + + private void resolveMayProvideIntents(IntentAttachPointType extensionType, + ModelResolver resolver) throws ContributionResolveException { + if (extensionType != null) { + // resolve all provided intents + List mayProvide = new ArrayList(); + for (Intent providedIntent : extensionType.getMayProvideIntents()) { + if (providedIntent.isUnresolved()) { + providedIntent = resolver.resolveModel(Intent.class, providedIntent); + if (!providedIntent.isUnresolved()) { + mayProvide.add(providedIntent); + } else { + throw new ContributionResolveException( + "May Provide Intent - " + providedIntent + + " not found for ExtensionType " + + extensionType); + + } + } else { + mayProvide.add(providedIntent); + } + } + extensionType.getMayProvideIntents().clear(); + extensionType.getMayProvideIntents().addAll(mayProvide); + } + } + + public Class getModelType() { + return IntentAttachPointType.class; + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyConstants.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyConstants.java new file mode 100644 index 0000000000..655b592665 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyConstants.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.policy.xml; + +import javax.xml.namespace.QName; + +/** + * constants related to policy framework + * + */ +public interface PolicyConstants { + String WHITE_SPACE = " "; + String COLON = ":"; + String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0"; + String TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.0"; + String INTENT = "intent"; + String POLICY_SET = "policySet"; + String POLICY_SET_REFERENCE = "policySetReference"; + String INTENT_MAP = "intentMap"; + String NAME = "name"; + String TARGET_NAMESPACE = "targetNamespace"; + String SCA_DEFINITIONS = "definitions"; + String CONSTRAINS = "constrains"; + String DESCRIPTION = "description"; + String PROVIDES = "provides"; + String APPLIES_TO = "appliesTo"; + String ALWAYS_APPLIES_TO = "alwaysAppliesTo"; + String QUALIFIER = "."; + String INTENT_MAP_QUALIFIER = "qualifier"; + String REQUIRES = "requires"; + String DEFAULT = "default"; + + String WS_POLICY_NS = "http://schemas.xmlsoap.org/ws/2004/09/policy"; + String WS_POLICY = "Policy"; + + String ALWAYS_PROVIDES = "alwaysProvides"; + String MAY_PROVIDE = "mayProvide"; + String TYPE = "type"; + String IMPLEMENTATION_TYPE = "implementationType"; + String BINDING_TYPE = "bindingType"; + QName IMPLEMENTATION_TYPE_QNAME = new QName(SCA10_NS, IMPLEMENTATION_TYPE); + QName BINDING_TYPE_QNAME = new QName(SCA10_NS, BINDING_TYPE); + String BINDING = "binding"; + String IMPLEMENTATION = "implementation"; + + QName POLICY_INTENT_QNAME = new QName(SCA10_NS, INTENT); + QName POLICY_SET_QNAME = new QName(SCA10_NS, POLICY_SET); + QName POLICY_INTENT_MAP_QNAME = new QName(SCA10_NS, INTENT_MAP); + QName SCA_DEFINITIONS_QNAME = new QName(SCA10_NS, SCA_DEFINITIONS); + QName DESCRIPTION_QNAME = new QName(SCA10_NS, DESCRIPTION); + QName POLICY_INTENT_MAP_QUALIFIER_QNAME = new QName(SCA10_NS, INTENT_MAP_QUALIFIER); + QName POLICY_SET_REFERENCE_QNAME = new QName(SCA10_NS, POLICY_SET_REFERENCE); + QName WS_POLICY_QNAME = new QName(WS_POLICY_NS, WS_POLICY); + + String QUALIFIED_INTENT_CONSTRAINS_ERROR = " - Qualified Intents must not specify 'constrains' attribute"; + + + + + +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyIntentProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyIntentProcessor.java new file mode 100644 index 0000000000..53231f704e --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicyIntentProcessor.java @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.policy.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +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.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.ProfileIntent; +import org.apache.tuscany.sca.policy.QualifiedIntent; + +/* * + * Processor for handling XML models of PolicyIntent definitions + */ + +public abstract class PolicyIntentProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor, PolicyConstants { + + private PolicyFactory policyFactory; + + public PolicyIntentProcessor(ModelFactoryExtensionPoint modelFactories) { + this.policyFactory = modelFactories.getFactory(PolicyFactory.class); + } + + public PolicyIntentProcessor(PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + this.policyFactory = policyFactory; + } + + public T read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + Intent policyIntent = null; + String policyIntentName = reader.getAttributeValue(null, NAME); + // Read an + if (reader.getAttributeValue(null, REQUIRES) != null) { + policyIntent = policyFactory.createProfileIntent(); + } else if ( policyIntentName != null && policyIntentName.indexOf(QUALIFIER) != -1) { + policyIntent = policyFactory.createQualifiedIntent(); + + int qualifierIndex = policyIntentName.lastIndexOf(QUALIFIER); + Intent qualifiableIntent = policyFactory.createIntent(); + qualifiableIntent.setUnresolved(true); + qualifiableIntent.setName(new QName(policyIntentName.substring(0, qualifierIndex))); + + ((QualifiedIntent)policyIntent).setQualifiableIntent(qualifiableIntent); + } else { + policyIntent = policyFactory.createIntent(); + } + policyIntent.setName(new QName(policyIntentName)); + + if ( policyIntent instanceof ProfileIntent ) { + readRequiredIntents((ProfileIntent)policyIntent, reader); + } + + readConstrainedArtifacts(policyIntent, reader); + + int event = reader.getEventType(); + QName name = null; + while (reader.hasNext()) { + event = reader.getEventType(); + switch (event) { + case START_ELEMENT : { + name = reader.getName(); + if (DESCRIPTION_QNAME.equals(name)) { + policyIntent.setDescription(reader.getElementText()); + } + break; + } + } + if (event == END_ELEMENT && POLICY_INTENT_QNAME.equals(reader.getName())) { + break; + } + + //Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + return (T)policyIntent; + } + + public void write(T policyIntent, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + // Write an + writer.writeStartElement(PolicyConstants.SCA10_NS, INTENT); + writer.writeNamespace(policyIntent.getName().getPrefix(), policyIntent.getName().getNamespaceURI()); + writer.writeAttribute(PolicyConstants.NAME, + policyIntent.getName().getPrefix() + COLON + policyIntent.getName().getLocalPart()); + if (policyIntent instanceof ProfileIntent) { + ProfileIntent profileIntent = (ProfileIntent)policyIntent; + if (profileIntent.getRequiredIntents() != null && + profileIntent.getRequiredIntents().size() > 0) { + StringBuffer sb = new StringBuffer(); + for (Intent requiredIntents : profileIntent.getRequiredIntents()) { + sb.append(requiredIntents.getName()); + sb.append(" "); + } + writer.writeAttribute(PolicyConstants.REQUIRES, sb.toString()); + } + } + + if (!(policyIntent instanceof QualifiedIntent) ) { + if (policyIntent.getConstrains() != null && + policyIntent.getConstrains().size() > 0) { + StringBuffer sb = new StringBuffer(); + for (QName contrainedArtifact : policyIntent.getConstrains()) { + sb.append(contrainedArtifact.toString()); + sb.append(" "); + } + writer.writeAttribute(CONSTRAINS, sb.toString()); + } else { + throw new ContributionWriteException("Contrains attribute missing from " + + "Policy Intent Definition" + policyIntent.getName()); + } + } + + if ( policyIntent.getDescription() != null && policyIntent.getDescription().length() > 0) { + writer.writeStartElement(PolicyConstants.SCA10_NS, DESCRIPTION); + writer.writeCData(policyIntent.getDescription()); + writer.writeEndElement(); + } + + writer.writeEndElement(); + } + + //FIXME This method is never used +// private Intent resolveRequiredIntents(ProfileIntent policyIntent, ModelResolver resolver) throws ContributionResolveException { +// boolean isUnresolved = false; +// //FIXME: Need to check for cyclic references first i.e an A requiring B and then B requiring A... +// if (policyIntent != null && policyIntent.isUnresolved()) { +// +// //resolve all required intents +// List requiredIntents = new ArrayList(); +// for (Intent requiredIntent : policyIntent.getRequiredIntents()) { +// if ( requiredIntent.isUnresolved() ) { +// //policyIntent.getRequiredIntents().remove(requiredIntent); +// requiredIntent = resolver.resolveModel(Intent.class, requiredIntent); +// requiredIntents.add(requiredIntent); +// if (requiredIntent.isUnresolved()) { +// isUnresolved = true; +// } +// } +// } +// policyIntent.getRequiredIntents().clear(); +// policyIntent.getRequiredIntents().addAll(requiredIntents); +// } +// policyIntent.setUnresolved(isUnresolved); +// +// return policyIntent; +// } + + //FIXME This method is never used +// private Intent resolveQualifiableIntent(QualifiedIntent policyIntent, ModelResolver resolver) throws ContributionResolveException { +// boolean isUnresolved = false; +// +// if (policyIntent != null && policyIntent.isUnresolved()) { +// //resolve the qualifiable intent +// Intent qualifiableIntent = +// resolver.resolveModel(Intent.class, policyIntent.getQualifiableIntent()); +// policyIntent.setQualifiableIntent(qualifiableIntent); +// isUnresolved = qualifiableIntent.isUnresolved(); +// } +// policyIntent.setUnresolved(isUnresolved); +// +// return policyIntent; +// } + + private void resolveContrainedArtifacts(Intent policyIntent, ModelResolver resolver) { + //FIXME : need to figure out this resolution. + policyIntent.setUnresolved(false); + } + + private void resolveProfileIntent(ProfileIntent policyIntent, ModelResolver resolver) + throws ContributionResolveException { + // FIXME: Need to check for cyclic references first i.e an A requiring B + // and then B requiring A... + if (policyIntent != null) { + // resolve all required intents + List requiredIntents = new ArrayList(); + for (Intent requiredIntent : policyIntent.getRequiredIntents()) { + if (requiredIntent.isUnresolved()) { + Intent resolvedRequiredIntent = resolver.resolveModel(Intent.class, requiredIntent); + if (resolvedRequiredIntent != null) { + requiredIntents.add(resolvedRequiredIntent); + } else { + throw new ContributionResolveException( + "Required Intent - " + requiredIntent + + " not found for ProfileIntent " + + policyIntent); + + } + } else { + requiredIntents.add(requiredIntent); + } + } + policyIntent.getRequiredIntents().clear(); + policyIntent.getRequiredIntents().addAll(requiredIntents); + } + } + + private void resolveQualifiedIntent(QualifiedIntent policyIntent, ModelResolver resolver) + throws ContributionResolveException { + if (policyIntent != null) { + //resolve the qualifiable intent + Intent qualifiableIntent = policyIntent.getQualifiableIntent(); + if (qualifiableIntent.isUnresolved()) { + Intent resolvedQualifiableIntent = resolver.resolveModel(Intent.class, qualifiableIntent); + + if (resolvedQualifiableIntent != null) { + policyIntent.setQualifiableIntent(resolvedQualifiableIntent); + } else { + throw new ContributionResolveException("Qualifiable Intent - " + qualifiableIntent + + " not found for QualifiedIntent " + + policyIntent); + } + + } + } + } + + public void resolve(T policyIntent, ModelResolver resolver) throws ContributionResolveException { + if (policyIntent instanceof ProfileIntent) { + resolveProfileIntent((ProfileIntent)policyIntent, resolver); + } + + if (policyIntent instanceof QualifiedIntent) { + resolveQualifiedIntent((QualifiedIntent)policyIntent, resolver); + } + + resolveContrainedArtifacts(policyIntent, resolver); + + if ( !policyIntent.isUnresolved() ) { + resolver.addModel(policyIntent); + } + } + + public QName getArtifactType() { + return POLICY_INTENT_QNAME; + } + + private void readConstrainedArtifacts(Intent policyIntent, XMLStreamReader reader) throws ContributionReadException { + String value = reader.getAttributeValue(null, CONSTRAINS); + if ( policyIntent instanceof QualifiedIntent && value != null) { + String errorMsg = + "Error in PolicyIntent Definition - " + policyIntent.getName() + QUALIFIED_INTENT_CONSTRAINS_ERROR; + throw new ContributionReadException(errorMsg); + } else { + if (value != null) { + List constrainedArtifacts = policyIntent.getConstrains(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + constrainedArtifacts.add(qname); + } + } + } + } + + private void readRequiredIntents(ProfileIntent policyIntent, XMLStreamReader reader) { + String value = reader.getAttributeValue(null, REQUIRES); + if (value != null) { + List requiredIntents = policyIntent.getRequiredIntents(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + Intent intent = policyFactory.createIntent(); + intent.setName(qname); + intent.setUnresolved(true); + requiredIntents.add(intent); + } + } + } + +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java new file mode 100644 index 0000000000..cf58964a89 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java @@ -0,0 +1,479 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.policy.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.axiom.om.OMAbstractFactory; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMFactory; +import org.apache.axiom.om.OMNamespace; +import org.apache.neethi.Policy; +import org.apache.neethi.PolicyEngine; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; + + +/** + * Processor for handling XML models of PolicySet definitions + */ +public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor, PolicyConstants { + + private PolicyFactory policyFactory; + private StAXArtifactProcessor extensionProcessor; + // private XPathFactory xpathFactory = XPathFactory.newInstance(); + + public PolicySetProcessor(ModelFactoryExtensionPoint modelFactories) { + this.policyFactory = modelFactories.getFactory(PolicyFactory.class); + } + + public PolicySetProcessor(PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + this.policyFactory = policyFactory; + this.extensionProcessor = extensionProcessor; + } + + public PolicySet read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + throw new IllegalArgumentException("not implemented in Android"); + /*String policySetName = reader.getAttributeValue(null, NAME); + + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(new QName(policySetName)); + String appliesTo = reader.getAttributeValue(null, APPLIES_TO); + String alwaysAppliesTo = reader.getAttributeValue(TUSCANY_NS, ALWAYS_APPLIES_TO); + + //TODO: with 1.0 version of specs the applies to xpath is given related to the immediate + //parent whereas the runtime evaluates the xpath aginst the composite element. What the runtime + //is doing is what the future version of the specs could be tending towards. When that happens + //this 'if' must be deleted + if ( appliesTo != null && !appliesTo.startsWith("/") ) { + appliesTo = "//" + appliesTo; + } + + if ( alwaysAppliesTo != null && !alwaysAppliesTo.startsWith("/") ) { + alwaysAppliesTo = "//" + alwaysAppliesTo; + } + + policySet.setAppliesTo(appliesTo); + policySet.setAlwaysAppliesTo(alwaysAppliesTo); + + XPath path = xpathFactory.newXPath(); + path.setNamespaceContext(reader.getNamespaceContext()); + try { + if (appliesTo != null) { + policySet.setAppliesToXPathExpression(path.compile(appliesTo)); + } + if (alwaysAppliesTo != null) { + policySet.setAlwaysAppliesToXPathExpression(path.compile(alwaysAppliesTo)); + } + } catch (XPathExpressionException e) { + throw new ContributionReadException(e); + } + + readProvidedIntents(policySet, reader); + + int event = reader.getEventType(); + QName name = null; + reader.next(); + while (reader.hasNext()) { + event = reader.getEventType(); + switch (event) { + case START_ELEMENT : { + name = reader.getName(); + if ( POLICY_INTENT_MAP_QNAME.equals(name) ) { + Intent mappedIntent = policyFactory.createIntent(); + mappedIntent.setName(getQName(reader, PROVIDES)); + if ( policySet.getProvidedIntents().contains(mappedIntent) ) { + readIntentMap(reader, policySet, mappedIntent); + } else { + throw new ContributionReadException("Intent Map provides for Intent not spcified as provided by parent PolicySet - " + policySetName); + } + } else if ( POLICY_SET_REFERENCE_QNAME.equals(name) ) { + PolicySet referredPolicySet = policyFactory.createPolicySet(); + referredPolicySet.setName(getQName(reader, NAME)); + policySet.getReferencedPolicySets().add(referredPolicySet); + } else if ( WS_POLICY_QNAME.equals(name) ) { + OMElement policyElement = loadElement(reader); + org.apache.neethi.Policy wsPolicy = PolicyEngine.getPolicy(policyElement); + policySet.getPolicies().add(wsPolicy); + } else { + Object extension = extensionProcessor.read(reader); + if ( extension != null ) { + policySet.getPolicies().add(extension); + } + } + break; + } + } + if ( event == END_ELEMENT ) { + if ( POLICY_SET_QNAME.equals(reader.getName()) ) { + break; + } + } + + //Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + return policySet; + } + + + public void readIntentMap(XMLStreamReader reader, PolicySet policySet, Intent mappedIntent) throws ContributionReadException { + QName name = reader.getName(); + Map> mappedPolicies = policySet.getMappedPolicies(); + if ( POLICY_INTENT_MAP_QNAME.equals(name) ) { + //Intent mappedIntent = policyFactory.createIntent(); + //mappedIntent.setName(getQName(reader, PROVIDES)); + String defaultQualifier = getString(reader, DEFAULT); + + String qualifierName = null; + String qualfiedIntentName = null; + Intent qualifiedIntent = null; + + int event = reader.getEventType(); + try { + reader.next(); + while (reader.hasNext()) { + event = reader.getEventType(); + switch (event) { + case START_ELEMENT : { + name = reader.getName(); + if ( POLICY_INTENT_MAP_QUALIFIER_QNAME.equals(name)) { + qualifierName = getString(reader, NAME); + qualfiedIntentName = mappedIntent.getName().getLocalPart() + + QUALIFIER + qualifierName; + qualifiedIntent = policyFactory.createIntent(); + qualifiedIntent.setName(new QName(mappedIntent.getName().getNamespaceURI(), + qualfiedIntentName)); + } else if ( POLICY_INTENT_MAP_QNAME.equals(name) ) { + QName providedIntent = getQName(reader, PROVIDES); + if ( qualifierName.equals(providedIntent.getLocalPart()) ) { + readIntentMap(reader, policySet, qualifiedIntent); + } else { + throw new ContributionReadException("Intent provided by IntentMap " + + providedIntent + " does not match parent qualifier " + qualifierName + + " in policyset - " + policySet); + } + } else if ( WS_POLICY_QNAME.equals(name) ) { + OMElement policyElement = loadElement(reader); + Policy wsPolicy = PolicyEngine.getPolicy(policyElement); + policySet.getPolicies().add(wsPolicy); + + List policyList = mappedPolicies.get(qualifiedIntent); + if ( policyList == null ) { + policyList = new ArrayList(); + mappedPolicies.put(qualifiedIntent, policyList); + + if (qualifierName.equals(defaultQualifier)) { + mappedPolicies.put(mappedIntent, policyList); + } + } + policyList.add((Policy)wsPolicy); + } else { + Object extension = extensionProcessor.read(reader); + if ( extension != null ) { + List policyList = mappedPolicies.get(qualifiedIntent); + if ( policyList == null ) { + policyList = new ArrayList(); + mappedPolicies.put(qualifiedIntent, policyList); + + if (qualifierName.equals(defaultQualifier)) { + mappedPolicies.put(mappedIntent, policyList); + } + } + policyList.add(extension); + } + } + break; + } + case END_ELEMENT : { + if ( POLICY_INTENT_MAP_QNAME.equals(reader.getName()) ) { + if ( defaultQualifier != null ) { + String qualifiedIntentName = mappedIntent.getName().getLocalPart() + QUALIFIER + defaultQualifier; + Intent defaultQualifiedIntent = policyFactory.createIntent(); + defaultQualifiedIntent.setName(new QName(mappedIntent.getName().getNamespaceURI(), + qualifiedIntentName)); + List policyList = mappedPolicies.get(defaultQualifiedIntent); + if ( policyList != null ) { + mappedPolicies.put(mappedIntent, policyList); + } else { + throw new ContributionReadException("Unable to map policies for default qualifier in IntentMap for - " + + mappedIntent + " in policy set - " + policySet); + } + defaultQualifier = null; + } + } + break; + } + } + if ( event == END_ELEMENT && POLICY_INTENT_MAP_QNAME.equals(reader.getName()) ) { + break; + } + //Read the next element + if (reader.hasNext()) { + reader.next(); + } + } + } catch (XMLStreamException e) { + throw new ContributionReadException(e); + } + }*/ + } + + public void write(PolicySet policySet, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + // Write an + writer.writeStartElement(SCA10_NS, POLICY_SET); + writer.writeNamespace(policySet.getName().getPrefix(), policySet.getName().getNamespaceURI()); + writer.writeAttribute(NAME, + policySet.getName().getPrefix() + COLON + policySet.getName().getLocalPart()); + writer.writeAttribute(APPLIES_TO, policySet.getAppliesTo()); + writer.writeAttribute(TUSCANY_NS, ALWAYS_APPLIES_TO, policySet.getAlwaysAppliesTo()); + + writeProvidedIntents(policySet, writer); + + writer.writeEndElement(); + } + + private void readProvidedIntents(PolicySet policySet, XMLStreamReader reader) { + String value = reader.getAttributeValue(null, PROVIDES); + if (value != null) { + List providedIntents = policySet.getProvidedIntents(); + for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { + QName qname = getQNameValue(reader, tokens.nextToken()); + Intent intent = policyFactory.createIntent(); + intent.setName(qname); + providedIntents.add(intent); + } + } + } + + private void writeProvidedIntents(PolicySet policySet, XMLStreamWriter writer) throws XMLStreamException { + if (policySet.getProvidedIntents() != null && + policySet.getProvidedIntents().size() > 0) { + StringBuffer sb = new StringBuffer(); + for (Intent providedIntents : policySet.getProvidedIntents()) { + sb.append(providedIntents.getName()); + sb.append(" "); + } + writer.writeAttribute(PolicyConstants.PROVIDES, sb.toString()); + } + } + + private void resolvePolicies(PolicySet policySet, ModelResolver resolver) throws ContributionResolveException { + boolean unresolved = false; + for ( Object o : policySet.getPolicies() ) { + extensionProcessor.resolve(o, resolver); + /*if ( o instanceof Policy && ((Policy)o).isUnresolved() ) { + unresolved = true; + }*/ + } + policySet.setUnresolved(unresolved); + } + + + + public QName getArtifactType() { + return POLICY_SET_QNAME; + } + + public Class getModelType() { + return PolicySet.class; + } + + private OMElement loadElement(XMLStreamReader reader) throws XMLStreamException { + OMFactory fac = OMAbstractFactory.getOMFactory(); + OMElement head = fac.createOMElement(reader.getName()); + OMElement current = head; + + while (true) { + switch (reader.next()) { + case XMLStreamConstants.START_ELEMENT: + QName name = reader.getName(); + OMElement child = fac.createOMElement(name, current); + + int count = reader.getNamespaceCount(); + for (int i = 0; i < count; i++) { + String prefix = reader.getNamespacePrefix(i); + String ns = reader.getNamespaceURI(i); + child.declareNamespace(ns, prefix); + } + + if(!"".equals(name.getNamespaceURI())) { + child.declareNamespace(name.getNamespaceURI(), name.getPrefix()); + } + + // add the attributes for this element + count = reader.getAttributeCount(); + for (int i = 0; i < count; i++) { + OMNamespace omNs = null; + String ns = reader.getAttributeNamespace(i); + String prefix = reader.getAttributePrefix(i); + String qname = reader.getAttributeLocalName(i); + String value = reader.getAttributeValue(i); + + if ( ns != null ) { + omNs = fac.createOMNamespace(ns, prefix); + } + + child.addAttribute(qname, value, omNs); + if (ns != null) { + child.declareNamespace(ns, prefix); + } + } + current = child; + break; + case XMLStreamConstants.CDATA: + fac.createOMText(current, reader.getText()); + break; + case XMLStreamConstants.CHARACTERS: + fac.createOMText(current, reader.getText()); + break; + case XMLStreamConstants.END_ELEMENT: + if ( current == head ) { + return head; + } else { + current = (OMElement)current.getParent(); + } + } + } + } + + private void resolveProvidedIntents(PolicySet policySet, ModelResolver resolver) throws ContributionResolveException { + if (policySet != null) { + //resolve all provided intents + List providedIntents = new ArrayList(); + for (Intent providedIntent : policySet.getProvidedIntents()) { + if (providedIntent.isUnresolved()) { + Intent resolvedProvidedIntent = resolver.resolveModel(Intent.class, providedIntent); + if (resolvedProvidedIntent != null) { + providedIntents.add(resolvedProvidedIntent); + } else { + throw new ContributionResolveException("Provided Intent - " + providedIntent + + " not found for PolicySet " + + policySet); + + } + } else { + providedIntents.add(providedIntent); + } + } + policySet.getProvidedIntents().clear(); + policySet.getProvidedIntents().addAll(providedIntents); + } + } + + private void resolveIntentsInMappedPolicies(PolicySet policySet, ModelResolver resolver) throws ContributionResolveException { + Map> mappedPolicies = new Hashtable>(); + for (Map.Entry> entry : policySet.getMappedPolicies().entrySet()) { + Intent mappedIntent = entry.getKey(); + if (mappedIntent.isUnresolved()) { + Intent resolvedMappedIntent = resolver.resolveModel(Intent.class, mappedIntent); + + if (resolvedMappedIntent != null) { + mappedPolicies.put(resolvedMappedIntent, entry.getValue()); + } else { + throw new ContributionResolveException("Mapped Intent - " + mappedIntent + + " not found for PolicySet " + + policySet); + + } + } else { + mappedPolicies.put(mappedIntent, entry.getValue()); + } + } + + policySet.getMappedPolicies().clear(); + policySet.getMappedPolicies().putAll(mappedPolicies); + } + + private void resolveReferredPolicySets(PolicySet policySet, ModelResolver resolver) throws ContributionResolveException { + + List referredPolicySets = new ArrayList(); + for (PolicySet referredPolicySet : policySet.getReferencedPolicySets()) { + if (referredPolicySet.isUnresolved()) { + PolicySet resolvedReferredPolicySet = resolver.resolveModel(PolicySet.class, referredPolicySet); + if (resolvedReferredPolicySet != null) { + referredPolicySets.add(resolvedReferredPolicySet); + } else { + throw new ContributionResolveException("Referred PolicySet - " + referredPolicySet + + "not found for PolicySet - " + + policySet); + } + } else { + referredPolicySets.add(referredPolicySet); + } + } + policySet.getReferencedPolicySets().clear(); + policySet.getReferencedPolicySets().addAll(referredPolicySets); + } + + private void includeReferredPolicySets(PolicySet policySet, PolicySet referredPolicySet) { + for (PolicySet furtherReferredPolicySet : referredPolicySet.getReferencedPolicySets()) { + includeReferredPolicySets(referredPolicySet, furtherReferredPolicySet); + } + policySet.getPolicies().addAll(referredPolicySet.getPolicies()); + policySet.getMappedPolicies().putAll(referredPolicySet.getMappedPolicies()); + } + + public void resolve(PolicySet policySet, ModelResolver resolver) throws ContributionResolveException { + resolveProvidedIntents(policySet, resolver); + resolveIntentsInMappedPolicies(policySet, resolver); + resolveReferredPolicySets(policySet, resolver); + + for (PolicySet referredPolicySet : policySet.getReferencedPolicySets()) { + includeReferredPolicySets(policySet, referredPolicySet); + } + + if ( policySet.isUnresolved() ) { + //resolve the policy attachments + resolvePolicies(policySet, resolver); + + if ( !policySet.isUnresolved() ) { + resolver.addModel(policySet); + } + } + } + } diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ProfileIntentProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ProfileIntentProcessor.java new file mode 100644 index 0000000000..4ad09baf55 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/ProfileIntentProcessor.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.policy.xml; + +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.ProfileIntent; + +/** + * Processor for handling XML models of PolicyIntent definitions that are ProfileIntents + */ +public class ProfileIntentProcessor extends PolicyIntentProcessor { + + public ProfileIntentProcessor(PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + super(policyFactory, extensionProcessor); + } + + public Class getModelType() { + return ProfileIntent.class; + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/QualifiedIntentProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/QualifiedIntentProcessor.java new file mode 100644 index 0000000000..cf4eef074f --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/QualifiedIntentProcessor.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.policy.xml; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.QualifiedIntent; + +/* + * Processor for handling XML models of PolicyIntent definitions that are QualifiedIntents + */ +public class QualifiedIntentProcessor extends PolicyIntentProcessor { + + public QualifiedIntentProcessor(ModelFactoryExtensionPoint modelFactories) { + super(modelFactories.getFactory(PolicyFactory.class), null); + } + + public QualifiedIntentProcessor(PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + super(policyFactory, extensionProcessor); + } + + public Class getModelType() { + return QualifiedIntent.class; + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/SimpleIntentProcessor.java b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/SimpleIntentProcessor.java new file mode 100644 index 0000000000..1977e544c4 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/java/org/apache/tuscany/sca/policy/xml/SimpleIntentProcessor.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.policy.xml; + +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/* + * Processor for handling XML models of PolicyIntent definitions + */ +public class SimpleIntentProcessor extends PolicyIntentProcessor { + + public SimpleIntentProcessor(PolicyFactory policyFactory, StAXArtifactProcessor extensionProcessor) { + super(policyFactory, extensionProcessor); + } + + public Class getModelType() { + return Intent.class; + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-android/tuscany-policy-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..0741e3eb76 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -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. + +# Implementation class for the artifact processor extension +#org.apache.tuscany.sca.policy.xml.SimpleIntentProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#intent,model=org.apache.tuscany.sca.policy.Intent +#org.apache.tuscany.sca.policy.xml.PolicySetProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#policySet,model=org.apache.tuscany.sca.policy.PolicySet +#org.apache.tuscany.sca.policy.xml.ProfileIntentProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#intent,model=org.apache.tuscany.sca.policy.ProfileIntent +#org.apache.tuscany.sca.policy.xml.QualifiedIntentProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#intent,model=org.apache.tuscany.sca.policy.QualifiedIntent diff --git a/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/MockPolicyProcessor.java b/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/MockPolicyProcessor.java new file mode 100644 index 0000000000..56d9a1eba8 --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/MockPolicyProcessor.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.policy.xml; + +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.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.policy.Policy; + +public class MockPolicyProcessor implements StAXArtifactProcessor { + + public QName getArtifactType() { + return new QName("http://schemas.xmlsoap.org/ws/2004/09/policy", "PolicyAttachment"); + } + + public Policy read(XMLStreamReader arg0) throws ContributionReadException, XMLStreamException { + return new MockPolicyImplOne(); + } + + public void write(Policy arg0, XMLStreamWriter arg1) throws ContributionWriteException, + XMLStreamException { + } + + public Class getModelType() { + // TODO Auto-generated method stub + return Policy.class; + } + + public void resolve(Policy arg0, ModelResolver arg1) throws ContributionResolveException { + + } + + + public class MockPolicyImplOne implements Policy { + public QName getSchemaName() { + return new QName("http://schemas.xmlsoap.org/ws/2004/09/policy", "PolicyAttachment"); + } + + public boolean isUnresolved() { + return false; + } + + public void setUnresolved(boolean unresolved) { + } + + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/ReadDocumentTestCase.java b/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/ReadDocumentTestCase.java new file mode 100644 index 0000000000..15b1eb149c --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/ReadDocumentTestCase.java @@ -0,0 +1,251 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.policy.xml; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import java.io.InputStream; +import java.net.URL; +import java.util.Hashtable; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.neethi.Policy; +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.ProfileIntent; +import org.apache.tuscany.sca.policy.QualifiedIntent; +import org.apache.tuscany.sca.policy.impl.BindingTypeImpl; +import org.apache.tuscany.sca.policy.impl.ImplementationTypeImpl; + +/** + * Test reading SCA XML assembly documents. + * + * @version $Rev: 551296 $ $Date: 2007-06-28 01:18:35 +0530 (Thu, 28 Jun 2007) $ + */ +public class ReadDocumentTestCase extends TestCase { + + //private ModelResolver resolver; + PolicySetProcessor policySetProcessor; + TestModelResolver resolver = null; + ExtensibleStAXArtifactProcessor staxProcessor = null; + + + Map intentTable = new Hashtable(); + Map policySetTable = new Hashtable(); + Map bindingTypesTable = new Hashtable(); + Map implTypesTable = new Hashtable(); + public static final String scaNamespace = "http://www.osoa.org/xmlns/sca/1.0"; + public static final String namespace = "http://test"; + + private static final QName secureWsPolicy = new QName(namespace, "SecureWSPolicy"); + private static final QName confidentiality = new QName(namespace, "confidentiality"); + private static final QName integrity = new QName(namespace, "integrity"); + private static final QName messageProtection = new QName(namespace, "messageProtection"); + private static final QName confidentiality_transport = new QName(namespace, "confidentiality.transport"); + private static final QName confidentiality_message = new QName(namespace, "confidentiality.message"); + private static final QName secureReliablePolicy = new QName(namespace, "SecureReliablePolicy"); + private static final QName secureMessagingPolicies = new QName(namespace, "SecureMessagingPolicies"); + private static final QName securityPolicy = new QName(namespace, "SecurityPolicy"); + private static final QName basicAuthMsgProtSecurity = new QName(namespace, "BasicAuthMsgProtSecurity"); + private static final QName wsBinding = new QName(scaNamespace, "binding.ws"); + private static final QName javaImpl = new QName(scaNamespace, "implementation.java"); + + + @Override + public void setUp() throws Exception { + resolver = new TestModelResolver(); + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + IntentAttachPointTypeFactory intentAttachPointFactory = new DefaultIntentAttachPointTypeFactory(); + DefaultStAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(new DefaultModelFactoryExtensionPoint()); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, XMLInputFactory.newInstance(), XMLOutputFactory.newInstance()); + + staxProcessors.addArtifactProcessor(new SimpleIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ProfileIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new QualifiedIntentProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new PolicySetProcessor(policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ImplementationTypeProcessor(policyFactory, intentAttachPointFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new BindingTypeProcessor(policyFactory, intentAttachPointFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new MockPolicyProcessor()); + + URL url = getClass().getResource("test_definitions.xml"); + InputStream urlStream = url.openStream(); + XMLStreamReader reader = inputFactory.createXMLStreamReader(urlStream); + QName name = null; + reader.next(); + while ( true ) { + int event = reader.getEventType(); + switch (event) { + case START_ELEMENT: { + Object artifact = staxProcessor.read(reader); + if ( artifact instanceof PolicySet ) { + PolicySet policySet = (PolicySet)artifact; + policySet.setName(new QName(namespace, policySet.getName().getLocalPart())); + policySetTable.put(policySet.getName(), policySet); + } else if ( artifact instanceof Intent ) { + Intent intent = (Intent)artifact; + intent.setName(new QName(namespace, intent.getName().getLocalPart())); + if ( intent instanceof QualifiedIntent ) { + ((QualifiedIntent)intent).getQualifiableIntent(). + setName(new QName(namespace, + ((QualifiedIntent)intent).getQualifiableIntent().getName().getLocalPart())); + } + intentTable.put(intent.getName(), intent); + } else if ( artifact instanceof BindingTypeImpl ) { + IntentAttachPointType bindingType = (IntentAttachPointType)artifact; + bindingTypesTable.put(bindingType.getName(), bindingType); + } else if ( artifact instanceof ImplementationTypeImpl ) { + IntentAttachPointType implType = (IntentAttachPointType)artifact; + implTypesTable.put(implType.getName(), implType); + } + + if ( artifact != null ) { + resolver.addModel(artifact); + } + + break; + } + } + if ( reader.hasNext() ) { + reader.next(); + } else { + break; + } + } + urlStream.close(); + } + + @Override + public void tearDown() throws Exception { + } + + public void testReadSCADefinitions() throws Exception { + assertNotNull(intentTable.get(confidentiality)); + assertNotNull(intentTable.get(messageProtection)); + assertNotNull(intentTable.get(confidentiality_transport)); + assertTrue(intentTable.get(confidentiality).getDescription().length() > 0 ); + + assertNotNull(policySetTable.get(secureReliablePolicy)); + assertTrue(policySetTable.get(secureReliablePolicy).getProvidedIntents().size() == 2); + assertTrue(policySetTable.get(secureReliablePolicy).getPolicies().size() == 2); + + assertNotNull(policySetTable.get(secureMessagingPolicies)); + assertEquals(policySetTable.get(secureMessagingPolicies).getMappedPolicies().size(), 3); + assertTrue(policySetTable.get(secureWsPolicy).getPolicies().get(0) instanceof Policy); + + assertEquals(bindingTypesTable.size(), 1); + assertNotNull(bindingTypesTable.get(wsBinding)); + assertEquals(implTypesTable.size(), 1); + assertNotNull(implTypesTable.get(javaImpl)); + } + + public void testResolution() throws Exception { + assertTrue(intentTable.get(messageProtection) instanceof ProfileIntent); + ProfileIntent profileIntent = (ProfileIntent)intentTable.get(new QName(namespace, "messageProtection")); + assertNull(profileIntent.getRequiredIntents().get(0).getDescription()); + + QName confidentiality_transport = new QName(namespace, "confidentiality.transport"); + assertTrue(intentTable.get(confidentiality_transport) instanceof QualifiedIntent); + QualifiedIntent qualifiedIntent = (QualifiedIntent)intentTable.get(new QName(namespace, "confidentiality.transport")); + assertNull(qualifiedIntent.getQualifiableIntent().getDescription()); + + PolicySet secureReliablePolicySet = policySetTable.get(secureReliablePolicy); + PolicySet secureMessagingPolicySet = policySetTable.get(secureMessagingPolicies); + PolicySet securityPolicySet = policySetTable.get(securityPolicy); + + assertEquals(secureReliablePolicySet.getProvidedIntents().get(1).getName(), integrity); + assertNull(secureReliablePolicySet.getProvidedIntents().get(1).getDescription()); + assertTrue(secureMessagingPolicySet.isUnresolved()); + assertEquals(securityPolicySet.getMappedPolicies().size(), 5); + + //testing to ensure that inclusion of referred policy sets has not happened + PolicySet basicAuthMsgProtSecurityPolicySet = policySetTable.get(basicAuthMsgProtSecurity); + assertTrue(basicAuthMsgProtSecurityPolicySet.getPolicies().isEmpty()); + assertTrue(basicAuthMsgProtSecurityPolicySet.getMappedPolicies().isEmpty()); + + IntentAttachPointType wsBindingType = bindingTypesTable.get(wsBinding); + assertNull(wsBindingType.getAlwaysProvidedIntents().get(0).getDescription()); + assertNull(wsBindingType.getMayProvideIntents().get(0).getDescription()); + + IntentAttachPointType javaImplType = implTypesTable.get(javaImpl); + assertNull(javaImplType.getAlwaysProvidedIntents().get(0).getDescription()); + assertNull(javaImplType.getMayProvideIntents().get(0).getDescription()); + + for ( Intent intent : intentTable.values() ) { + staxProcessor.resolve(intent, resolver); + } + + for ( PolicySet policySet : policySetTable.values() ) { + staxProcessor.resolve(policySet, resolver); + } + + for ( IntentAttachPointType bindingType : bindingTypesTable.values() ) { + staxProcessor.resolve(bindingType, resolver); + } + + for ( IntentAttachPointType implType : implTypesTable.values() ) { + staxProcessor.resolve(implType, resolver); + } + + + + //testing if policy intents have been linked have property been linked up + assertNotNull(profileIntent.getRequiredIntents().get(0).getDescription()); + assertNotNull(qualifiedIntent.getQualifiableIntent().getDescription()); + assertEquals(secureReliablePolicySet.getProvidedIntents().get(1).getName(), integrity); + assertNotNull(secureReliablePolicySet.getProvidedIntents().get(1).getDescription()); + + //testing if policysets have been properly linked up with intents + assertFalse(secureMessagingPolicySet.isUnresolved()); + assertNotNull(secureMessagingPolicySet.getMappedPolicies().get(intentTable.get(confidentiality))); + assertNotNull(secureMessagingPolicySet.getMappedPolicies().get(intentTable.get(confidentiality_transport))); + + //testing if intent maps have been properly mapped to policies + assertFalse(securityPolicySet.isUnresolved()); + assertNotNull(securityPolicySet.getMappedPolicies().get(intentTable.get(confidentiality))); + assertNotNull(securityPolicySet.getMappedPolicies().get(intentTable.get(confidentiality_message))); + + //testing for inclusion of referred policysets + assertFalse(basicAuthMsgProtSecurityPolicySet.getPolicies().isEmpty()); + assertFalse(basicAuthMsgProtSecurityPolicySet.getMappedPolicies().isEmpty()); + assertNotNull(basicAuthMsgProtSecurityPolicySet.getMappedPolicies().get(intentTable.get(confidentiality_transport))); + + assertNotNull(wsBindingType.getAlwaysProvidedIntents().get(0).getDescription()); + assertNotNull(wsBindingType.getMayProvideIntents().get(0).getDescription()); + + assertNotNull(javaImplType.getAlwaysProvidedIntents().get(0).getDescription()); + assertNotNull(javaImplType.getMayProvideIntents().get(0).getDescription()); + } +} diff --git a/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/TestModelResolver.java b/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/TestModelResolver.java new file mode 100644 index 0000000000..ce999539bb --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/test/java/org/apache/tuscany/sca/policy/xml/TestModelResolver.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.policy.xml; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A default implementation of an artifact resolver, based on a map. + * + * @version $Rev: 560306 $ $Date: 2007-07-27 22:01:44 +0530 (Fri, 27 Jul 2007) $ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map map = new HashMap(); + + public TestModelResolver() { + } + + public T resolveModel(Class modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + } + + public Object removeModel(Object resolved) { + return map.remove(resolved); + } + +} diff --git a/branches/sca-android/tuscany-policy-xml/src/test/resources/org/apache/tuscany/sca/policy/xml/test_definitions.xml b/branches/sca-android/tuscany-policy-xml/src/test/resources/org/apache/tuscany/sca/policy/xml/test_definitions.xml new file mode 100644 index 0000000000..e01a29863a --- /dev/null +++ b/branches/sca-android/tuscany-policy-xml/src/test/resources/org/apache/tuscany/sca/policy/xml/test_definitions.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + Test Intent + + + + + + Protect messages from unauthorized reading or modification + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ... + + + + ... + + + + + + + + + + + sp:X509v3 + + + + + + + + + + + + + + + + + + Protect messages from unauthorized reading or modification + + + + + + Protect messages from unauthorized reading or modification + + + + + + + Communitcation thro this binding must prevent + unauthorized users from reading the messages. + + + + + + Communitcation thro this binding must prevent + unauthorized modification of the messages. + + + + + + Communitcation thro this binding required + Authentication. + + + + + + All messages to and from this implementation must be logged + + + + + + Need to figure out some description for this + + + + \ No newline at end of file -- cgit v1.2.3