From 3caf8614f25d6b1962e20331fdf423c863bc02f3 Mon Sep 17 00:00:00 2001 From: lresende Date: Wed, 11 Nov 2009 23:13:31 +0000 Subject: Moving 1.x branches git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835144 13f79535-47bb-0310-9956-ffa450edef68 --- .../binding/local/AbstractLocalTargetInvoker.java | 77 ++ .../core/binding/local/LocalBindingBuilder.java | 56 ++ .../core/binding/local/LocalBindingDefinition.java | 45 ++ .../core/binding/local/LocalBindingLoader.java | 70 ++ .../binding/local/LocalCallbackTargetInvoker.java | 74 ++ .../core/binding/local/LocalReferenceBinding.java | 61 ++ .../core/binding/local/LocalServiceBinding.java | 55 ++ .../core/binding/local/LocalTargetInvoker.java | 73 ++ .../tuscany/core/bootstrap/Bootstrapper.java | 88 +++ .../core/bootstrap/DefaultBootstrapper.java | 262 +++++++ .../tuscany/core/bootstrap/DefaultRuntime.java | 83 ++ .../tuscany/core/bootstrap/DefaultSCARuntime.java | 92 +++ .../tuscany/core/builder/BuilderRegistryImpl.java | 293 +++++++ .../apache/tuscany/core/builder/ConnectorImpl.java | 627 +++++++++++++++ .../core/builder/IllegalCallbackException.java | 54 ++ .../builder/IncompatibleInterfacesException.java | 93 +++ .../core/builder/InvalidTargetTypeException.java | 41 + .../builder/NoCompatibleBindingsException.java | 36 + .../builder/NoConversationalContractException.java | 37 + .../core/builder/NoRegisteredBuilderException.java | 38 + .../builder/TargetServiceNotFoundException.java | 42 + .../tuscany/core/builder/WireConnectException.java | 58 ++ .../builder/WirePostProcessorRegistryImpl.java | 57 ++ .../core/builder/WiringExceptionFormatter.java | 72 ++ .../core/component/ComponentContextImpl.java | 85 ++ .../tuscany/core/component/ScopeIdentifier.java | 35 + .../tuscany/core/component/WorkContextImpl.java | 211 +++++ .../core/component/event/AbstractEvent.java | 39 + .../core/component/event/AbstractRequestEvent.java | 38 + .../core/component/event/CompositeEvent.java | 33 + .../core/component/event/CompositeStart.java | 47 ++ .../core/component/event/CompositeStop.java | 46 ++ .../core/component/event/ConversationEnd.java | 31 + .../core/component/event/ConversationStart.java | 31 + .../core/component/event/ConversationalEvent.java | 39 + .../core/component/event/HttpRequestEnded.java | 38 + .../core/component/event/HttpRequestStart.java | 38 + .../core/component/event/HttpSessionEnd.java | 38 + .../core/component/event/HttpSessionEvent.java | 45 ++ .../core/component/event/HttpSessionStart.java | 38 + .../tuscany/core/component/event/RequestEnd.java | 38 + .../tuscany/core/component/event/RequestEvent.java | 28 + .../tuscany/core/component/event/RequestStart.java | 37 + .../component/scope/AbstractScopeContainer.java | 158 ++++ .../component/scope/CompositeScopeContainer.java | 189 +++++ .../scope/CompositeScopeObjectFactory.java | 50 ++ .../scope/ConversationalScopeContainer.java | 217 ++++++ .../scope/ConversationalScopeObjectFactory.java | 58 ++ .../component/scope/HttpSessionScopeContainer.java | 135 ++++ .../scope/HttpSessionScopeObjectFactory.java | 54 ++ .../core/component/scope/InstanceWrapper.java | 41 + .../core/component/scope/InstanceWrapperImpl.java | 63 ++ .../component/scope/RequestScopeContainer.java | 126 +++ .../component/scope/RequestScopeObjectFactory.java | 47 ++ .../core/component/scope/ScopeRegistryImpl.java | 63 ++ .../component/scope/StatelessScopeContainer.java | 75 ++ .../scope/StatelessScopeObjectFactory.java | 54 ++ .../databinding/impl/DataBindingInteceptor.java | 250 ++++++ .../impl/DataBindingJavaInterfaceProcessor.java | 126 +++ .../databinding/impl/DataBindingRegistryImpl.java | 121 +++ .../impl/DataBindingWirePostProcessor.java | 157 ++++ .../core/databinding/impl/DataTypeLoader.java | 67 ++ .../core/databinding/impl/DirectedGraph.java | 357 +++++++++ .../impl/Exception2ExceptionTransformer.java | 126 +++ .../databinding/impl/Group2GroupTransformer.java | 97 +++ .../core/databinding/impl/GroupDataBinding.java | 97 +++ .../databinding/impl/Input2InputTransformer.java | 201 +++++ .../core/databinding/impl/MediatorImpl.java | 185 +++++ .../databinding/impl/Output2OutputTransformer.java | 186 +++++ .../databinding/impl/PassByValueInterceptor.java | 131 ++++ .../impl/PassByValueWirePostProcessor.java | 188 +++++ .../core/databinding/impl/PipedTransformer.java | 66 ++ .../core/databinding/impl/SimpleDataBinding.java | 61 ++ .../impl/TransformationContextImpl.java | 83 ++ .../databinding/impl/TransformerRegistryImpl.java | 101 +++ .../javabeans/DOMNode2JavaBeanTransformer.java | 78 ++ .../javabeans/Java2XMLMapperException.java | 69 ++ .../javabeans/JavaBean2DOMNodeTransformer.java | 70 ++ .../javabeans/JavaBean2XMLStreamReader.java | 56 ++ .../javabeans/JavaBean2XMLTransformer.java | 226 ++++++ .../javabeans/JavaBeansDataBinding.java | 107 +++ .../javabeans/XML2JavaBeanTransformer.java | 300 ++++++++ .../javabeans/XML2JavaMapperException.java | 76 ++ .../tuscany/core/databinding/xml/BeanUtil.java | 196 +++++ .../core/databinding/xml/DOMDataBinding.java | 52 ++ .../core/databinding/xml/DOMWrapperHandler.java | 78 ++ .../core/databinding/xml/DOMXMLStreamReader.java | 129 ++++ .../xml/DelegatingNamespaceContext.java | 310 ++++++++ .../core/databinding/xml/InputSource2Node.java | 65 ++ .../core/databinding/xml/InputSource2SAX.java | 63 ++ .../core/databinding/xml/InputStream2Node.java | 67 ++ .../core/databinding/xml/InputStream2SAX.java | 62 ++ .../xml/NameValueArrayStreamReader.java | 403 ++++++++++ .../databinding/xml/NameValuePairStreamReader.java | 347 +++++++++ .../core/databinding/xml/NamedProperty.java | 59 ++ .../databinding/xml/NilElementStreamReader.java | 279 +++++++ .../core/databinding/xml/Node2OutputStream.java | 66 ++ .../tuscany/core/databinding/xml/Node2String.java | 59 ++ .../tuscany/core/databinding/xml/Node2Writer.java | 65 ++ .../core/databinding/xml/Node2XMLStreamReader.java | 59 ++ .../tuscany/core/databinding/xml/Reader2Node.java | 65 ++ .../tuscany/core/databinding/xml/Reader2SAX.java | 58 ++ .../tuscany/core/databinding/xml/SAX2DOM.java | 244 ++++++ .../tuscany/core/databinding/xml/SAX2DOMPipe.java | 67 ++ .../databinding/xml/Source2ResultTransformer.java | 60 ++ .../core/databinding/xml/StAX2SAXAdapter.java | 256 ++++++ .../core/databinding/xml/StAXDataBinding.java | 52 ++ .../tuscany/core/databinding/xml/StAXHelper.java | 85 ++ .../core/databinding/xml/StreamDataPipe.java | 57 ++ .../tuscany/core/databinding/xml/String2Node.java | 60 ++ .../tuscany/core/databinding/xml/String2SAX.java | 59 ++ .../databinding/xml/String2XMLStreamReader.java | 55 ++ .../databinding/xml/WrappingXMLStreamReader.java | 230 ++++++ .../databinding/xml/Writer2ReaderDataPipe.java | 56 ++ .../databinding/xml/XMLDocumentStreamReader.java | 432 +++++++++++ .../databinding/xml/XMLFragmentStreamReader.java | 53 ++ .../xml/XMLFragmentStreamReaderImpl.java | 857 +++++++++++++++++++++ .../core/databinding/xml/XMLGroupDataBinding.java | 58 ++ .../core/databinding/xml/XMLStreamReader2Node.java | 62 ++ .../core/databinding/xml/XMLStreamReader2SAX.java | 73 ++ .../databinding/xml/XMLStreamReader2String.java | 55 ++ .../core/databinding/xml/XMLStreamSerializer.java | 266 +++++++ .../core/databinding/xml/XMLStreamable.java | 37 + .../core/databinding/xml/XMLStringDataBinding.java | 51 ++ .../core/deployer/AbstractDeploymentContext.java | 61 ++ .../core/deployer/ChildDeploymentContext.java | 60 ++ .../apache/tuscany/core/deployer/DeployerImpl.java | 176 +++++ .../core/deployer/RootDeploymentContext.java | 65 ++ .../deployer/federation/FederatedDeployer.java | 109 +++ .../core/idl/java/IllegalCallbackException.java | 34 + .../tuscany/core/idl/java/InterfaceJavaLoader.java | 117 +++ .../java/JavaInterfaceProcessorRegistryImpl.java | 169 ++++ .../implementation/IntrospectionRegistryImpl.java | 135 ++++ .../core/implementation/PojoAtomicComponent.java | 282 +++++++ .../core/implementation/PojoConfiguration.java | 232 ++++++ .../composite/AbstractCompositeBuilder.java | 61 ++ .../composite/AbstractCompositeComponent.java | 151 ++++ .../composite/AbstractCompositeContext.java | 124 +++ .../composite/ComponentTimeoutException.java | 33 + .../implementation/composite/CompositeBuilder.java | 50 ++ .../composite/CompositeComponentImpl.java | 114 +++ .../composite/CompositeComponentTypeLoader.java | 67 ++ .../implementation/composite/CompositeLoader.java | 426 ++++++++++ .../core/implementation/composite/Dependency.java | 39 + .../composite/ImplementationCompositeLoader.java | 126 +++ .../composite/ManagedRequestContext.java | 58 ++ .../implementation/composite/ReferenceImpl.java | 90 +++ .../core/implementation/composite/ServiceImpl.java | 98 +++ .../composite/SystemCompositeBuilder.java | 67 ++ .../composite/SystemSingletonAtomicComponent.java | 164 ++++ .../implementation/java/JavaAtomicComponent.java | 100 +++ .../implementation/java/JavaComponentBuilder.java | 208 +++++ .../java/JavaComponentTypeLoader.java | 141 ++++ .../implementation/java/JavaImplementation.java | 62 ++ .../java/JavaImplementationLoader.java | 65 ++ .../implementation/java/JavaTargetInvoker.java | 144 ++++ .../processor/AllowsPassByReferenceProcessor.java | 63 ++ .../processor/AmbiguousConstructorException.java | 41 + .../processor/ConstructorProcessor.java | 112 +++ .../implementation/processor/ContextProcessor.java | 140 ++++ .../processor/ConversationProcessor.java | 142 ++++ .../implementation/processor/DestroyProcessor.java | 62 ++ .../processor/DuplicateConstructorException.java | 38 + .../processor/DuplicateDestructorException.java | 37 + .../processor/DuplicateInitException.java | 37 + .../processor/DuplicateReferenceException.java | 38 + .../processor/DuplicateResourceException.java | 37 + .../processor/EagerInitProcessor.java | 59 ++ .../processor/HeuristicPojoProcessor.java | 550 +++++++++++++ .../IllegalCallbackReferenceException.java | 37 + .../processor/IllegalContextException.java | 37 + .../processor/IllegalDestructorException.java | 37 + .../processor/IllegalInitException.java | 36 + .../processor/IllegalReferenceException.java | 37 + .../processor/IllegalResourceException.java | 37 + .../IllegalServiceDefinitionException.java | 37 + .../ImplementationProcessorServiceImpl.java | 469 +++++++++++ .../implementation/processor/InitProcessor.java | 62 ++ .../processor/InvalidAutowireException.java | 34 + .../processor/InvalidConstructorException.java | 39 + .../InvalidConversationalImplementation.java | 45 ++ .../processor/InvalidPropertyException.java | 34 + .../processor/InvalidReferenceException.java | 41 + .../processor/InvalidResourceException.java | 33 + .../processor/InvalidServiceType.java | 34 + .../implementation/processor/MonitorProcessor.java | 57 ++ .../processor/NoConstructorException.java | 36 + .../processor/PropertyProcessor.java | 79 ++ .../processor/ReferenceProcessor.java | 184 +++++ .../processor/ResourceProcessor.java | 117 +++ .../implementation/processor/ScopeProcessor.java | 64 ++ .../implementation/processor/ServiceProcessor.java | 156 ++++ .../processor/ServiceTypeNotFoundException.java | 34 + .../processor/UnknownContextTypeException.java | 32 + .../system/builder/SystemComponentBuilder.java | 184 +++++ .../component/SystemAtomicComponentImpl.java | 55 ++ .../system/loader/SystemComponentTypeLoader.java | 101 +++ .../loader/SystemCompositeComponentTypeLoader.java | 70 ++ .../system/loader/SystemImplementationLoader.java | 75 ++ .../model/SystemCompositeImplementation.java | 57 ++ .../system/model/SystemImplementation.java | 51 ++ .../injection/ArrayMultiplicityObjectFactory.java | 54 ++ .../core/injection/CallbackWireObjectFactory.java | 47 ++ .../injection/CompositeContextObjectFactory.java | 48 ++ .../tuscany/core/injection/ContextInjector.java | 32 + .../injection/ConversationIDObjectFactory.java | 36 + .../tuscany/core/injection/EventInvoker.java | 34 + .../tuscany/core/injection/FieldInjector.java | 57 ++ .../core/injection/InjectionRuntimeException.java | 55 ++ .../apache/tuscany/core/injection/Injector.java | 35 + .../core/injection/InvalidAccessorException.java | 34 + .../injection/InvalidResourceTypeException.java | 33 + .../core/injection/JNDIListObjectFactory.java | 58 ++ .../tuscany/core/injection/JNDIObjectFactory.java | 50 ++ .../injection/ListMultiplicityObjectFactory.java | 50 ++ .../tuscany/core/injection/MethodEventInvoker.java | 55 ++ .../tuscany/core/injection/MethodInjector.java | 55 ++ .../core/injection/NoAccessorException.java | 39 + .../injection/NoMultiplicityTypeException.java | 29 + .../core/injection/ObjectCallbackException.java | 48 ++ .../tuscany/core/injection/PojoObjectFactory.java | 123 +++ .../injection/RequestContextObjectFactory.java | 26 + .../core/injection/ResourceNotFoundException.java | 34 + .../core/injection/ResourceObjectFactory.java | 146 ++++ .../core/injection/SingletonListObjectFactory.java | 42 + .../core/injection/SingletonObjectFactory.java | 39 + .../core/launcher/CompositeContextImpl.java | 60 ++ .../tuscany/core/launcher/LaunchException.java | 49 ++ .../apache/tuscany/core/launcher/LauncherImpl.java | 250 ++++++ .../tuscany/core/launcher/LauncherRuntimeInfo.java | 96 +++ .../tuscany/core/loader/ComponentLoader.java | 524 +++++++++++++ .../core/loader/ComponentTypeElementLoader.java | 90 +++ .../DefaultPropertyValueLoaderException.java | 32 + .../tuscany/core/loader/DependencyLoader.java | 88 +++ .../apache/tuscany/core/loader/IncludeLoader.java | 111 +++ .../tuscany/core/loader/JNDIPropertyFactory.java | 71 ++ .../core/loader/LoaderExceptionFormatter.java | 50 ++ .../tuscany/core/loader/LoaderRegistryImpl.java | 185 +++++ .../loader/ManyPropertyValueLoaderException.java | 32 + .../loader/MissingTypePropertyLoaderException.java | 32 + .../tuscany/core/loader/PolicySetLoader.java | 196 +++++ .../apache/tuscany/core/loader/PropertyLoader.java | 170 ++++ .../core/loader/PropertyLoaderException.java | 69 ++ .../tuscany/core/loader/ReferenceLoader.java | 196 +++++ .../apache/tuscany/core/loader/ServiceLoader.java | 106 +++ .../core/loader/StringParserPropertyFactory.java | 205 +++++ .../org/apache/tuscany/core/loader/WireLoader.java | 112 +++ .../marshaller/ComponentDefinitionMarshaller.java | 80 ++ .../core/monitor/DefaultExceptionFormatter.java | 54 ++ .../core/monitor/InvalidLevelException.java | 64 ++ .../core/monitor/JavaLoggingMonitorFactory.java | 321 ++++++++ .../tuscany/core/monitor/MonitorFactoryUtil.java | 78 ++ .../tuscany/core/monitor/NullMonitorFactory.java | 58 ++ .../tuscany/core/policy/IntentRegistryImpl.java | 167 ++++ .../core/policy/PolicyBuilderRegistryImpl.java | 79 ++ .../tuscany/core/policy/PolicyEngineImpl.java | 297 +++++++ .../apache/tuscany/core/policy/PolicyHelper.java | 65 ++ .../tuscany/core/property/PropertyHelper.java | 235 ++++++ .../core/property/PropertyObjectFactoryImpl.java | 147 ++++ .../SimpleMultivaluedPropertyObjectFactory.java | 74 ++ .../core/property/SimplePropertyObjectFactory.java | 64 ++ .../tuscany/core/runtime/AbstractRuntime.java | 283 +++++++ .../tuscany/core/runtime/mini/SimpleRuntime.java | 32 + .../core/runtime/mini/SimpleRuntimeImpl.java | 140 ++++ .../core/runtime/mini/SimpleRuntimeInfo.java | 48 ++ .../core/runtime/mini/SimpleRuntimeInfoImpl.java | 184 +++++ .../services/artifact/LocalMavenRepository.java | 100 +++ .../deployment/ArtifactResolverRegistryImpl.java | 70 ++ .../services/deployment/AssemblyServiceImpl.java | 156 ++++ .../deployment/ContentTypeDescriberImpl.java | 111 +++ .../deployment/ContributionDirectoryWatcher.java | 70 ++ .../services/deployment/ContributionLoader.java | 126 +++ .../ContributionProcessorRegistryImpl.java | 96 +++ .../deployment/ContributionRepositoryImpl.java | 275 +++++++ .../deployment/ContributionServiceImpl.java | 232 ++++++ .../services/deployment/DomainUpdateException.java | 47 ++ .../InvalidContributionMetadataException.java | 52 ++ .../deployment/InvalidDocumentException.java | 38 + .../services/deployment/XMLChangeSetHandler.java | 132 ++++ .../CompositeContributionProcessor.java | 102 +++ .../contribution/FolderContributionProcessor.java | 139 ++++ .../InvalidComponentDefinitionlException.java | 41 + .../InvalidFolderContributionURIException.java | 41 + .../InvalidPojoComponentDefinitionlException.java | 36 + .../contribution/JarContributionProcessor.java | 146 ++++ .../contribution/JavaContributionProcessor.java | 107 +++ .../MetadataContributionProcessor.java | 90 +++ .../ComponentDefinitionArtifactResolver.java | 69 ++ .../extension/AbstractExtensionDeployer.java | 122 +++ .../host/DelegatingResourceHostRegistry.java | 142 ++++ .../core/services/store/memory/MemoryStore.java | 198 +++++ .../core/services/work/jca/JcaWorkScheduler.java | 206 +++++ .../services/work/jsr237/Jsr237WorkScheduler.java | 217 ++++++ .../work/jsr237/workmanager/DefaultWorkEvent.java | 73 ++ .../work/jsr237/workmanager/DefaultWorkItem.java | 166 ++++ .../jsr237/workmanager/ThreadPoolWorkManager.java | 220 ++++++ .../tuscany/core/test/SCATestCaseRunner.java | 213 +++++ .../tuscany/core/util/ClassLoaderHelper.java | 93 +++ .../org/apache/tuscany/core/util/FileHelper.java | 704 +++++++++++++++++ .../org/apache/tuscany/core/util/IOHelper.java | 184 +++++ .../tuscany/core/util/JavaIntrospectionHelper.java | 439 +++++++++++ .../tuscany/core/util/ReferenceLoaderHelper.java | 167 ++++ .../tuscany/core/wire/BridgingInterceptor.java | 29 + .../core/wire/CallbackInterfaceInterceptor.java | 60 ++ .../core/wire/InboundInvocationChainImpl.java | 41 + .../apache/tuscany/core/wire/InboundWireImpl.java | 166 ++++ ...ompatibleServiceContractExceptionFormatter.java | 95 +++ .../tuscany/core/wire/InvocationChainImpl.java | 107 +++ .../tuscany/core/wire/InvokerInterceptor.java | 59 ++ .../org/apache/tuscany/core/wire/LoopBackWire.java | 33 + .../core/wire/NoMethodForOperationException.java | 42 + .../core/wire/NonBlockingBridgingInterceptor.java | 177 +++++ .../core/wire/OptimizedWireObjectFactory.java | 47 ++ .../core/wire/OutboundInvocationChainImpl.java | 53 ++ .../apache/tuscany/core/wire/OutboundWireImpl.java | 176 +++++ .../core/wire/SynchronousBridgingInterceptor.java | 55 ++ .../tuscany/core/wire/WireObjectFactory.java | 84 ++ .../tuscany/core/wire/WireServiceExtension.java | 323 ++++++++ .../org/apache/tuscany/core/wire/WireUtils.java | 146 ++++ .../wire/jdk/JDKCallbackInvocationHandler.java | 137 ++++ .../core/wire/jdk/JDKInboundInvocationHandler.java | 173 +++++ .../wire/jdk/JDKOutboundInvocationHandler.java | 249 ++++++ .../tuscany/core/wire/jdk/JDKWireService.java | 114 +++ 323 files changed, 35862 insertions(+) create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultSCARuntime.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Exception2ExceptionTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Group2GroupTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/GroupDataBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/BeanUtil.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DelegatingNamespaceContext.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValueArrayStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValuePairStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NamedProperty.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NilElementStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXDataBinding.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/WrappingXMLStreamReader.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLDocumentStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLGroupDataBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java create mode 100755 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIListObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonListObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DefaultPropertyValueLoaderException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ManyPropertyValueLoaderException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/MissingTypePropertyLoaderException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoaderException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/marshaller/ComponentDefinitionMarshaller.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimpleMultivaluedPropertyObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntime.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfo.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfoImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ArtifactResolverRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionLoader.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/DomainUpdateException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidContributionMetadataException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/CompositeContributionProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidPojoComponentDefinitionlException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/MetadataContributionProcessor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/resolver/ComponentDefinitionArtifactResolver.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/test/SCATestCaseRunner.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ReferenceLoaderHelper.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java create mode 100644 sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java (limited to 'sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache') diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java new file mode 100644 index 0000000000..7727759a88 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/AbstractLocalTargetInvoker.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Base class for dispatching to a composite reference using the local binding + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractLocalTargetInvoker implements TargetInvoker { + protected boolean cacheable; + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + public boolean isOptimizable() { + return isCacheable(); // we only need to check if the scopes are correct + } + + public Object invokeTarget(final Object payload, short sequence) throws InvocationTargetException { + throw new InvocationTargetException(new UnsupportedOperationException()); + } + + protected Message invoke(OutboundInvocationChain chain, TargetInvoker invoker, Message msg) throws Throwable { + Interceptor headInterceptor = chain.getHeadInterceptor(); + if (headInterceptor == null) { + try { + // short-circuit the dispatch and invoke the target directly + if (invoker == null) { + String name = chain.getOperation().getName(); + throw new AssertionError("No target invoker [" + name + "]"); + } + return invoker.invoke(msg); + } catch (InvocationRuntimeException e) { + // the cause was thrown by the target so throw it + throw e.getCause(); + } + } else { + msg.setTargetInvoker(invoker); + return headInterceptor.invoke(msg); + } + } + + @Override + public AbstractLocalTargetInvoker clone() throws CloneNotSupportedException { + return (AbstractLocalTargetInvoker) super.clone(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java new file mode 100644 index 0000000000..c62523889d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingBuilder.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.BindingBuilderExtension; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Creates runtime artifacts for the local binding + * + * @version $Rev$ $Date$ + */ +public class LocalBindingBuilder extends BindingBuilderExtension { + + protected Class getBindingType() { + return LocalBindingDefinition.class; + } + + public ServiceBinding build(CompositeComponent parent, + ServiceDefinition serviceDefinition, + LocalBindingDefinition bindingDefinition, + DeploymentContext deploymentContext) + throws BuilderException { + return new LocalServiceBinding(serviceDefinition.getName(), parent); + } + + + public ReferenceBinding build(CompositeComponent parent, + AbstractReferenceDefinition referenceDefinition, + LocalBindingDefinition bindingDefinition, + DeploymentContext deploymentContext) throws BuilderException { + return new LocalReferenceBinding(referenceDefinition.getName(), parent); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java new file mode 100644 index 0000000000..4df3e413dc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingDefinition.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import java.net.URI; + +import org.apache.tuscany.spi.model.BindingDefinition; + + +/** + * Represents the local by-reference binding + * + * @version $Rev$ $Date$ + */ +public class LocalBindingDefinition extends BindingDefinition implements Cloneable { + + public LocalBindingDefinition() { + } + + public LocalBindingDefinition(URI targetUri) { + super(targetUri); + } + + public Object clone() { + LocalBindingDefinition clone = new LocalBindingDefinition(); + clone.setTargetUri(URI.create(getTargetUri().toString())); + return clone; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java new file mode 100644 index 0000000000..777beeb00e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalBindingLoader.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import java.net.URI; +import java.net.URISyntaxException; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.wire.Wire; + +/** + * Loader responsible for handling the local binding + * + * @version $Rev$ $Date$ + */ +public class LocalBindingLoader extends LoaderExtension { + + /** + * Constructor specifies the registry to register with. + * + * @param registry the LoaderRegistry this loader should register with + */ + public LocalBindingLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return Wire.LOCAL_BINDING; + } + + public LocalBindingDefinition load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + String uri = reader.getAttributeValue(null, "uri"); + if (uri != null) { + try { + return new LocalBindingDefinition(new URI(uri)); + } catch (URISyntaxException e) { + throw new LoaderException(e); + } + } + return new LocalBindingDefinition(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java new file mode 100644 index 0000000000..03f42ca99c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalCallbackTargetInvoker.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import java.util.Map; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Dispatches a callback invocation to the callback instance + * + * @version $Rev$ $Date$ + */ +public class LocalCallbackTargetInvoker extends AbstractLocalTargetInvoker { + private Operation operation; + private InboundWire inboundWire; + + public LocalCallbackTargetInvoker(Operation operation, InboundWire inboundWire) { + assert operation != null : "Operation method cannot be null"; + this.operation = operation; + this.inboundWire = inboundWire; + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + return invoke(operation, msg); + } catch (Throwable e) { + Message faultMsg = new MessageImpl(); + faultMsg.setBodyWithFault(e); + return faultMsg; + } + } + + private Message invoke(Operation operation, Message msg) throws Throwable { + Object targetAddress = msg.popFromAddress(); + if (targetAddress == null) { + throw new AssertionError("Popped a null from address from message"); + } + //TODO optimize as this is slow in local invocations + Map, OutboundInvocationChain> sourceCallbackInvocationChains = + inboundWire.getSourceCallbackInvocationChains(targetAddress); + OutboundInvocationChain chain = sourceCallbackInvocationChains.get(operation); + TargetInvoker invoker = chain.getTargetInvoker(); + return invoke(chain, invoker, msg); + } + + @Override + public LocalCallbackTargetInvoker clone() throws CloneNotSupportedException { + return (LocalCallbackTargetInvoker) super.clone(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java new file mode 100644 index 0000000000..9117fe903e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalReferenceBinding.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.CoreRuntimeException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetInvokerCreationException; +import org.apache.tuscany.spi.extension.ReferenceBindingExtension; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.Wire; + +/** + * The runtime representaion of the local reference binding + * + * @version $Rev$ $Date$ + */ +public class LocalReferenceBinding extends ReferenceBindingExtension { + + public LocalReferenceBinding(String name, CompositeComponent parent) throws CoreRuntimeException { + super(name, parent); + } + + public QName getBindingType() { + return Wire.LOCAL_BINDING; + } + + public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation) + throws TargetInvokerCreationException { + if (operation.isCallback()) { + return new LocalCallbackTargetInvoker(operation, inboundWire); + } else { + return new LocalTargetInvoker(operation, outboundWire); + } + } + + public TargetInvoker createCallbackTargetInvoker(ServiceContract contract, Operation operation) + throws TargetInvokerCreationException { + return new LocalCallbackTargetInvoker(operation, inboundWire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java new file mode 100644 index 0000000000..6205172d7b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalServiceBinding.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.CoreRuntimeException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetInvokerCreationException; +import org.apache.tuscany.spi.extension.ServiceBindingExtension; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.Wire; + +/** + * The runtime representaion of the local service binding + * + * @version $Rev$ $Date$ + */ +public class LocalServiceBinding extends ServiceBindingExtension { + + public LocalServiceBinding(String name, CompositeComponent parent) throws CoreRuntimeException { + super(name, parent); + } + + public QName getBindingType() { + return Wire.LOCAL_BINDING; + } + + public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation) + throws TargetInvokerCreationException { + if (operation.isCallback()) { + return new LocalCallbackTargetInvoker(operation, getInboundWire()); + } else { + return new LocalTargetInvoker(operation, outboundWire); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java new file mode 100644 index 0000000000..5b564c93b8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/binding/local/LocalTargetInvoker.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.binding.local; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Dispatches an invocation through a composite service or reference using the local binding + * + * @version $Rev$ $Date$ + */ +public class LocalTargetInvoker extends AbstractLocalTargetInvoker { + private OutboundInvocationChain chain; + private Object fromAddress; + private boolean contractHasCallback; + + public LocalTargetInvoker(Operation operation, OutboundWire outboundWire) { + assert operation != null; + chain = outboundWire.getInvocationChains().get(operation); + assert chain != null; + fromAddress = (outboundWire.getContainer() == null) ? null : outboundWire.getContainer().getName(); + contractHasCallback = outboundWire.getServiceContract().getCallbackClass() != null; + } + + @Override + public LocalTargetInvoker clone() throws CloneNotSupportedException { + return (LocalTargetInvoker) super.clone(); + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + TargetInvoker invoker = chain.getTargetInvoker(); + assert invoker != null; + // Pushing the from address only needs to happen in the outbound (forward) direction for callbacks + if (contractHasCallback) { + msg.pushFromAddress(fromAddress); + } + + return invoke(chain, invoker, msg); + } catch (Throwable e) { + Message faultMsg = new MessageImpl(); + faultMsg.setBodyWithFault(e); + return faultMsg; + } + } + + + public boolean isOptimizable() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java new file mode 100644 index 0000000000..0f6b4a2c92 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.loader.Loader; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; + +/** + * Interface that abstracts the process used to create a running Tuscany system. Implementation of this may provide + * different mechanisms for creating the primoridal system components used to boot the core to the level where it can + * support end-user applications. + * + * @version $Rev$ $Date$ + */ +public interface Bootstrapper { + /** + * Return the MonitorFactory being used by the implementation to provide monitor interfaces for the primordial + * components. + * + * @return the MonitorFactory being used by the bootstrapper + */ + MonitorFactory getMonitorFactory(); + + /** + * Create the RuntimeComponent that forms the fundamental root of the component assembly. This component has two + * children: a {@link org.apache.tuscany.spi.component.CompositeComponent} that is the root for all system + * components, and a {@link org.apache.tuscany.spi.component.CompositeComponent} that is the root for all + * application components. + * + * @return a new RuntimeComponent; basically a new Tuscany instance + */ + RuntimeComponent createRuntime(); + + /** + * Create a Deployer that can be used to deploy the system definition. This will most likely only support a small + * subset of the available programming model. + * + * @return a new primordial Deployer + */ + Deployer createDeployer(); + + /** + * Create a Loader for parsing a system definition represented as a XML SCDL file. + * + * @param propertyFactory the StAXPropertyFactory to be used to parse property values + * @param introspector the introspector to be used to extract component type information from a Java class + * @return a new prmordial Loader + */ + Loader createLoader(PropertyObjectFactory propertyFactory, Introspector introspector); + + /** + * Create a ScopeRegistry that supports the Scopes supported for primordial components + * + * @param workContext the WorkContext the Scopes should use + * @return a new primordial ScopeRegistry + */ + ScopeRegistry createScopeRegistry(WorkContext workContext); + + /** + * Create a Connector that can wire together primordial components. + * + * @return a new primordial Connector + */ + Connector createConnector(); +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java new file mode 100644 index 0000000000..762568eb01 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.builder.Builder; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.services.management.TuscanyManagementService; + +import org.apache.tuscany.core.binding.local.LocalBindingBuilder; +import org.apache.tuscany.core.binding.local.LocalBindingDefinition; +import org.apache.tuscany.core.binding.local.LocalBindingLoader; +import org.apache.tuscany.core.builder.BuilderRegistryImpl; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.scope.CompositeScopeObjectFactory; +import org.apache.tuscany.core.component.scope.ScopeRegistryImpl; +import org.apache.tuscany.core.deployer.DeployerImpl; +import org.apache.tuscany.core.idl.java.InterfaceJavaLoader; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.IntrospectionRegistryImpl; +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; +import org.apache.tuscany.core.implementation.composite.CompositeLoader; +import org.apache.tuscany.core.implementation.processor.ConstructorProcessor; +import org.apache.tuscany.core.implementation.processor.DestroyProcessor; +import org.apache.tuscany.core.implementation.processor.EagerInitProcessor; +import org.apache.tuscany.core.implementation.processor.HeuristicPojoProcessor; +import org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl; +import org.apache.tuscany.core.implementation.processor.InitProcessor; +import org.apache.tuscany.core.implementation.processor.MonitorProcessor; +import org.apache.tuscany.core.implementation.processor.PropertyProcessor; +import org.apache.tuscany.core.implementation.processor.ReferenceProcessor; +import org.apache.tuscany.core.implementation.processor.ResourceProcessor; +import org.apache.tuscany.core.implementation.processor.ScopeProcessor; +import org.apache.tuscany.core.implementation.processor.ServiceProcessor; +import org.apache.tuscany.core.implementation.system.builder.SystemComponentBuilder; +import org.apache.tuscany.core.implementation.composite.SystemCompositeBuilder; +import org.apache.tuscany.core.implementation.system.loader.SystemComponentTypeLoader; +import org.apache.tuscany.core.implementation.system.loader.SystemCompositeComponentTypeLoader; +import org.apache.tuscany.core.implementation.system.loader.SystemImplementationLoader; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.loader.ComponentLoader; +import org.apache.tuscany.core.loader.ComponentTypeElementLoader; +import org.apache.tuscany.core.loader.IncludeLoader; +import org.apache.tuscany.core.loader.LoaderRegistryImpl; +import org.apache.tuscany.core.loader.PropertyLoader; +import org.apache.tuscany.core.loader.ReferenceLoader; +import org.apache.tuscany.core.loader.ServiceLoader; +import org.apache.tuscany.core.property.PropertyObjectFactoryImpl; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import org.apache.tuscany.host.MonitorFactory; + +/** + * A default implementation of a Bootstrapper. Please see the documentation on the individual methods for how the + * primordial components are created. + * + * @version $Rev$ $Date$ + */ +public class DefaultBootstrapper implements Bootstrapper { + private final MonitorFactory monitorFactory; + private final XMLInputFactory xmlFactory; + private final TuscanyManagementService managementService; + + /** + * Create a default bootstrapper. + * + * @param monitorFactory the MonitorFactory to be used to create monitors for the primordial components + * @param xmlFactory the XMLInputFactory to be used by the components to load XML artifacts + * @param managementService management service used by the runtime. + */ + public DefaultBootstrapper(MonitorFactory monitorFactory, + XMLInputFactory xmlFactory, + TuscanyManagementService managementService) { + this.monitorFactory = monitorFactory; + this.xmlFactory = xmlFactory; + this.managementService = managementService; + } + + /** + * Returns the MonitorFactory being used by this bootstrapper. + * + * @return the MonitorFactory being used by this bootstrapper + */ + public MonitorFactory getMonitorFactory() { + return monitorFactory; + } + + /** + * Create the RuntimeComponent that will form the root of the component tree. Returns an new instance of a {@link + * DefaultRuntime} with the system and application root components initialized with default composite components. + * + * @return a newly created root for the component tree + */ + public RuntimeComponent createRuntime() { + DefaultRuntime runtime = new DefaultRuntime(); + CompositeComponent systemComponent = + new CompositeComponentImpl(ComponentNames.TUSCANY_SYSTEM_ROOT, runtime, null, true); + runtime.setSystemComponent(systemComponent); + CompositeComponent rootComponent = + new CompositeComponentImpl(ComponentNames.TUSCANY_APPLICATION_ROOT, runtime, null, null); + runtime.setRootComponent(rootComponent); + return runtime; + } + + /** + * Create primordial deployer that can be used to load the system definition. + * + * @return the primordial deployer + */ + public Deployer createDeployer() { + ScopeRegistry scopeRegistry = createScopeRegistry(new WorkContextImpl()); + Builder builder = createBuilder(scopeRegistry); + JavaInterfaceProcessorRegistry interfaceIntrospector = new JavaInterfaceProcessorRegistryImpl(); + Introspector introspector = createIntrospector(interfaceIntrospector); + LoaderRegistry loader = createLoader(new PropertyObjectFactoryImpl(), introspector); + DeployerImpl deployer = new DeployerImpl(xmlFactory, loader, builder); + deployer.setMonitor(getMonitorFactory().getMonitor(ScopeContainerMonitor.class)); + return deployer; + } + + /** + * Create a basic ScopeRegistry containing the ScopeContainers that are available to components in the system + * definition. The implementation returned only support COMPOSITE scope. + * + * @param workContext the WorkContext the scopes should use + * @return a new ScopeRegistry + */ + public ScopeRegistry createScopeRegistry(WorkContext workContext) { + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(); + new CompositeScopeObjectFactory(scopeRegistry, monitorFactory.getMonitor(ScopeContainerMonitor.class)); + return scopeRegistry; + } + + /** + * Create a Loader that can be used to parse an XML file containing the SCDL for the system definition. The + * following Implementation types are supported:
  • SystemImplementation
  • + *
  • SystemCompositeImplementation
and the following SCDL elements are supported:
    + *
  • composite
  • component
  • componentType
  • interface.java
  • property
  • + *
  • reference
  • service
  • implementation.system
Note the Java component type and the + * WSDL interface type are not supported. + * + * @param propertyFactory the StAXPropertyFactory to be used for parsing Property values + * @param introspector the Introspector to be used to inspect component implementations + * @return a new StAX XML loader + */ + public LoaderRegistry createLoader(PropertyObjectFactory propertyFactory, Introspector introspector) { + LoaderRegistryImpl loaderRegistry = + new LoaderRegistryImpl(monitorFactory.getMonitor(LoaderRegistryImpl.Monitor.class)); + + // register component type loaders + loaderRegistry.registerLoader(SystemImplementation.class, new SystemComponentTypeLoader(introspector)); + loaderRegistry.registerLoader(SystemCompositeImplementation.class, + new SystemCompositeComponentTypeLoader(loaderRegistry)); + + // register element loaders + registerLoader(loaderRegistry, new ComponentLoader(loaderRegistry, propertyFactory)); + registerLoader(loaderRegistry, new ComponentTypeElementLoader(loaderRegistry)); + registerLoader(loaderRegistry, new CompositeLoader(loaderRegistry, null)); + registerLoader(loaderRegistry, new IncludeLoader(loaderRegistry)); + JavaInterfaceProcessorRegistryImpl processorRegistry = new JavaInterfaceProcessorRegistryImpl(); + registerLoader(loaderRegistry, new InterfaceJavaLoader(loaderRegistry, processorRegistry)); + registerLoader(loaderRegistry, new PropertyLoader(loaderRegistry)); + registerLoader(loaderRegistry, new ReferenceLoader(loaderRegistry)); + registerLoader(loaderRegistry, new ServiceLoader(loaderRegistry)); + registerLoader(loaderRegistry, new SystemImplementationLoader(loaderRegistry)); + registerLoader(loaderRegistry, new LocalBindingLoader(loaderRegistry)); + return loaderRegistry; + } + + /** + * Create new Introspector for extracting a ComponentType definition from a Java class. + * + * @return a new Introspector + */ + public Introspector createIntrospector(JavaInterfaceProcessorRegistry registry) { + ImplementationProcessorService service = new ImplementationProcessorServiceImpl(registry); + IntrospectionRegistryImpl.Monitor monitor = monitorFactory.getMonitor(IntrospectionRegistryImpl.Monitor.class); + IntrospectionRegistryImpl introspectionRegistry = new IntrospectionRegistryImpl(monitor); + introspectionRegistry.registerProcessor(new ConstructorProcessor(service)); + introspectionRegistry.registerProcessor(new DestroyProcessor()); + introspectionRegistry.registerProcessor(new InitProcessor()); + introspectionRegistry.registerProcessor(new EagerInitProcessor()); + introspectionRegistry.registerProcessor(new ScopeProcessor()); + introspectionRegistry.registerProcessor(new PropertyProcessor(service)); + introspectionRegistry.registerProcessor(new ReferenceProcessor(registry)); + introspectionRegistry.registerProcessor(new ResourceProcessor()); + introspectionRegistry.registerProcessor(new ServiceProcessor(service)); + introspectionRegistry.registerProcessor(new HeuristicPojoProcessor(service)); + introspectionRegistry.registerProcessor(new MonitorProcessor(monitorFactory, service)); + return introspectionRegistry; + } + + /** + * Create a new Connector that can be used to wire primordial components together. + * + * @return a new Connector + */ + public Connector createConnector() { + return new ConnectorImpl(); + } + + /** + * Helper method for registering a loader with the registry. The Loader is registered once for the QName returned by + * its {@link LoaderExtension#getXMLType()} method. + * + * @param registry the LoaderRegistry to register with + * @param loader the Loader to register + */ + protected void registerLoader(LoaderRegistry registry, LoaderExtension loader) { + registry.registerLoader(loader.getXMLType(), loader); + } + + /** + * Create a Builder that can be used to build the components in the system definition. The default implementation + * only supports implementations from the system programming model. + * + * @param scopeRegistry the ScopeRegistry defining the component scopes that will be supported + * @return a new Builder + */ + private Builder createBuilder(ScopeRegistry scopeRegistry) { + BuilderRegistryImpl builderRegistry = + new BuilderRegistryImpl(scopeRegistry, new JDKWireService()); + SystemCompositeBuilder builder = + new SystemCompositeBuilder(builderRegistry, createConnector(), managementService); + builderRegistry.register(SystemCompositeImplementation.class, builder); + builderRegistry.register(SystemImplementation.class, new SystemComponentBuilder()); + builderRegistry.register(LocalBindingDefinition.class, new LocalBindingBuilder()); + return builderRegistry; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java new file mode 100644 index 0000000000..978d10fc37 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.wire.InboundWire; + +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; + +/** + * The default implementation of the Tuscany runtime component + * + * @version $Rev$ $Date$ + */ +public class DefaultRuntime extends CompositeComponentImpl implements RuntimeComponent { + private CompositeComponent rootComponent; + private CompositeComponent systemComponent; + + /** + * Initialize a default runtime with an empty set of Property values. + */ + public DefaultRuntime() { + this(new HashMap()); + } + + /** + * Initialize a runtime with the a set of properties + * + * @param runtimeProperties Property values for the runtime itself + */ + public DefaultRuntime(Map runtimeProperties) { + super(ComponentNames.TUSCANY_RUNTIME, null, null, runtimeProperties); + } + + protected void setRootComponent(CompositeComponent rootComponent) { + this.rootComponent = rootComponent; + } + + protected void setSystemComponent(CompositeComponent systemComponent) { + this.systemComponent = systemComponent; + } + + public CompositeComponent getRootComponent() { + return rootComponent; + } + + public CompositeComponent getSystemComponent() { + return systemComponent; + } + + public Deployer getDeployer() throws TargetResolutionException { + InboundWire wire = systemComponent.resolveExternalAutowire(Deployer.class); + if (wire != null) { + return (Deployer) wire.getTargetService(); + } + return null; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultSCARuntime.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultSCARuntime.java new file mode 100644 index 0000000000..15172c60c0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultSCARuntime.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import java.net.URI; +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +import org.apache.tuscany.api.SCARuntime; +import org.apache.tuscany.api.TuscanyException; +import org.apache.tuscany.core.component.ComponentContextImpl; +import org.apache.tuscany.core.launcher.CompositeContextImpl; +import org.apache.tuscany.core.runtime.mini.SimpleRuntime; +import org.apache.tuscany.core.runtime.mini.SimpleRuntimeImpl; +import org.apache.tuscany.core.runtime.mini.SimpleRuntimeInfo; +import org.apache.tuscany.core.runtime.mini.SimpleRuntimeInfoImpl; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.CurrentCompositeContext; +import org.osoa.sca.ServiceUnavailableException; + +/** + * Default implementation of SCARuntime. + * + * @version $Rev$ $Date$ + */ +@SuppressWarnings("deprecation") +public class DefaultSCARuntime extends SCARuntime { + protected CompositeComponent application; + protected CompositeContextImpl context; + + protected SimpleRuntime runtime; + + protected void startup(URL system, URL[] exts, URL applicationSCDL, String compositePath) throws Exception { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + List extensions = exts == null ? null : Arrays.asList(exts); + URI contributionURI = URI.create("/default"); + SimpleRuntimeInfo runtimeInfo = + new SimpleRuntimeInfoImpl(cl, system, extensions, contributionURI, applicationSCDL, compositePath); + runtime = new SimpleRuntimeImpl(runtimeInfo); + + try { + application = runtime.start(); + } catch (TuscanyException e) { + throw e; + } + + } + + protected void shutdown() throws Exception { + runtime.destroy(); + } + + @Override + protected ComponentContext getContext(String componentName) { + CompositeComponent composite = ((CompositeContextImpl)context).getComposite(); + Component component = (Component)composite.getChild(componentName); + return new ComponentContextImpl(CurrentCompositeContext.getContext(), component); + } + + public CompositeComponent getCompsiteComponent() { + return application; + } + + @Override + public Object getSystemService(String serviceName) { + try { + return runtime.getSystemService(Object.class, serviceName); + } catch (TargetResolutionException e) { + throw new ServiceUnavailableException(e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java new file mode 100644 index 0000000000..2bb0524201 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.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.core.builder; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.binding.local.LocalBindingDefinition; +import org.apache.tuscany.core.implementation.composite.ReferenceImpl; +import org.apache.tuscany.core.implementation.composite.ServiceImpl; +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BindingBuilder; +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.builder.ComponentBuilder; +import org.apache.tuscany.spi.builder.GenericBuilder; +import org.apache.tuscany.spi.builder.MissingWireTargetException; +import org.apache.tuscany.spi.builder.ScopeNotFoundException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.BindingDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ComponentTypeReferenceDefinition; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.wire.WireService; +import org.osoa.sca.annotations.EagerInit; + +/** + * The default builder registry in the runtime + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class BuilderRegistryImpl implements BuilderRegistry { + protected WireService wireService; + protected ScopeRegistry scopeRegistry; + + private final Map>, ComponentBuilder>> componentBuilders = + new HashMap>, ComponentBuilder>>(); + private final Map, BindingBuilder> bindingBuilders = + new HashMap, BindingBuilder>(); + private final Map, GenericBuilder> genericBuilders = + new HashMap, GenericBuilder>(); + + public BuilderRegistryImpl(@Autowire + ScopeRegistry scopeRegistry, @Autowire + WireService wireService) { + this.scopeRegistry = scopeRegistry; + this.wireService = wireService; + } + + public > void register(Class implClass, ComponentBuilder builder) { + componentBuilders.put(implClass, builder); + } + + public > void unregisterComponentBuilder(Class implClass) { + componentBuilders.remove(implClass); + } + + public void register(Class implClass, BindingBuilder builder) { + bindingBuilders.put(implClass, builder); + } + + @SuppressWarnings("unchecked") + public > Component build(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext context) throws BuilderException { + + Class implClass = componentDefinition.getImplementation().getClass(); + // noinspection SuspiciousMethodCalls + ComponentBuilder componentBuilder = (ComponentBuilder)componentBuilders.get(implClass); + try { + if (componentBuilder == null) { + String name = implClass.getName(); + throw new NoRegisteredBuilderException("No builder registered for implementation", name); + } + + Component component = componentBuilder.build(parent, componentDefinition, context); + if (component != null) { + component.setDefaultPropertyValues(componentDefinition.getPropertyValues()); + Scope scope = componentDefinition.getImplementation().getComponentType().getImplementationScope(); + if (scope == Scope.SYSTEM || scope == Scope.COMPOSITE) { + component.setScopeContainer(context.getCompositeScope()); + } else { + // Check for conversational contract if conversational scope + if (scope == Scope.CONVERSATION) { + boolean hasConversationalContract = false; + ComponentType componentType = + componentDefinition.getImplementation().getComponentType(); + Map services = componentType.getServices(); + for (ServiceDefinition serviceDef : services.values()) { + InteractionScope intScope = serviceDef.getServiceContract().getInteractionScope(); + if (intScope == InteractionScope.CONVERSATIONAL) { + hasConversationalContract = true; + break; + } + } + if (!hasConversationalContract) { + Map references = componentType.getReferences(); + for (AbstractReferenceDefinition refDef : references.values()) { + // TODO check for a conversational callback + // contract + // refDef.getServiceContract() ... + } + } + if (!hasConversationalContract) { + String name = implClass.getName(); + throw new NoConversationalContractException("No conversational contract for conversational implementation", + name); + } + } + // Now it's ok to set the scope container + ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(scope); + if (scopeContainer == null) { + throw new ScopeNotFoundException(scope.toString()); + } + component.setScopeContainer(scopeContainer); + } + } + ComponentType componentType = componentDefinition.getImplementation().getComponentType(); + assert componentType != null : "Component type must be set"; + // create wires for the component + if (wireService != null && component instanceof AtomicComponent) { + wireService.createWires((AtomicComponent)component, componentDefinition); + } + // FIXME: Can we merge all the extensions at the component level? + buildExtensions(component, componentType, context); + buildExtensions(component, componentDefinition.getImplementation(), context); + buildExtensions(component, componentDefinition, context); + return component; + } catch (BuilderException e) { + e.addContextName(componentDefinition.getName()); + throw e; + } + } + + @SuppressWarnings({"unchecked"}) + public Service build(CompositeComponent parent, + ServiceDefinition serviceDefinition, + DeploymentContext deploymentContext) throws BuilderException { + String name = serviceDefinition.getName(); + ServiceContract serviceContract = serviceDefinition.getServiceContract(); + if (serviceDefinition.getBindings().isEmpty()) { + // if no bindings are configured, default to the local binding. + // this should be changed to allow runtime selection + if (serviceDefinition.getBindings().isEmpty()) { + // TODO JFM implement capability for the runtime to choose a + // binding + serviceDefinition.addBinding(new LocalBindingDefinition()); + } + } + boolean system = parent.isSystem(); + URI targetUri = serviceDefinition.getTarget(); + Service service = new ServiceImpl(name, parent, serviceContract, targetUri, system); + for (BindingDefinition definition : serviceDefinition.getBindings()) { + Class bindingClass = definition.getClass(); + // noinspection SuspiciousMethodCalls + BindingBuilder bindingBuilder = bindingBuilders.get(bindingClass); + if (bindingBuilder == null) { + throw new NoRegisteredBuilderException("No builder registered for type", bindingClass.getName()); + } + ServiceBinding binding = bindingBuilder.build(parent, serviceDefinition, definition, deploymentContext); + if (wireService != null) { + URI uri = serviceDefinition.getTarget(); + if (uri == null) { + throw new MissingWireTargetException("Service uri not specified"); + } + String path = uri.getPath(); + ServiceContract contract = serviceDefinition.getServiceContract(); + wireService.createWires(binding, contract, path); + } + buildExtensions(binding, definition, deploymentContext); + service.addServiceBinding(binding); + } + buildExtensions(service, serviceDefinition, deploymentContext); + return service; + } + + @SuppressWarnings("unchecked") + public Reference build(CompositeComponent parent, + AbstractReferenceDefinition referenceDefinition, + DeploymentContext context) + throws BuilderException { + String name = referenceDefinition.getName(); + ServiceContract contract = referenceDefinition.getServiceContract(); + if (referenceDefinition.getBindings().isEmpty()) { + // if no bindings are configured, default to the local binding. + // this should be changed to allow runtime selection + if (referenceDefinition.getBindings().isEmpty()) { + // TODO JFM implement capability for the runtime to choose a + // binding + referenceDefinition.addBinding(new LocalBindingDefinition()); + } + } + + Reference reference = new ReferenceImpl(name, parent, contract); + for (BindingDefinition bindingDefinition : referenceDefinition.getBindings()) { + Class bindingClass = bindingDefinition.getClass(); + // noinspection SuspiciousMethodCalls + BindingBuilder bindingBuilder = bindingBuilders.get(bindingClass); + ReferenceBinding binding = bindingBuilder.build(parent, referenceDefinition, bindingDefinition, context); + // create wires for the component + if (wireService != null) { + URI targetUri = bindingDefinition.getTargetUri(); + // it is possible for a binding to not have a URI + QualifiedName targetName = null; + if (targetUri != null) { + targetName = new QualifiedName(targetUri.getPath()); + } + wireService.createWires(binding, contract, targetName); + + } + buildExtensions(binding, bindingDefinition, context); + reference.addReferenceBinding(binding); + + } + buildExtensions(reference, referenceDefinition, context); + return reference; + } + + @SuppressWarnings("unchecked") + public SCAObject build(SCAObject parent, ModelObject modelObject, DeploymentContext context) + throws BuilderException { + if (modelObject != null) { + GenericBuilder builder = genericBuilders.get(modelObject.getClass()); + if (builder != null) { + return builder.build(parent, modelObject, context); + } + } + return null; + } + + // We need to include all the extensions from the include + private void buildExtensions(SCAObject parent, ModelObject model, DeploymentContext deploymentContext) + throws BuilderException { + for (Object o : model.getExtensions().values()) { + if (o instanceof ModelObject) { + SCAObject scaObject = build(parent, (ModelObject)o, deploymentContext); + if (scaObject != null) { + parent.getExtensions().put(scaObject.getName(), scaObject); + } + } + } + } + + public void register(Class modelClass, + GenericBuilder builder) { + genericBuilders.put(modelClass, builder); + } + + public void unregisterBindingBuilder(Class implClass) { + bindingBuilders.remove(implClass); + } + + public void unregisterGenericBuilder(Class modelClass) { + genericBuilders.remove(modelClass); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java new file mode 100644 index 0000000000..728b0b8fc9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java @@ -0,0 +1,627 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.List; +import java.util.Map; + +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.builder.MissingWireTargetException; +import org.apache.tuscany.spi.builder.WiringException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.component.TargetInvokerCreationException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.IncompatibleServiceContractException; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WirePostProcessorRegistry; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.wire.LoopBackWire; +import org.apache.tuscany.core.wire.NonBlockingBridgingInterceptor; +import org.apache.tuscany.core.wire.SynchronousBridgingInterceptor; +import org.apache.tuscany.core.wire.WireUtils; + +/** + * The default connector implmentation + * + * @version $$Rev$$ $$Date$$ + */ +public class ConnectorImpl implements Connector { + private WirePostProcessorRegistry postProcessorRegistry; + private WireService wireService; + private WorkContext workContext; + private WorkScheduler scheduler; + + public ConnectorImpl() { + } + + @Constructor + public ConnectorImpl(@Autowire WireService wireService, + @Autowire WirePostProcessorRegistry processorRegistry, + @Autowire WorkScheduler scheduler, + @Autowire WorkContext workContext) { + this.postProcessorRegistry = processorRegistry; + this.wireService = wireService; + this.scheduler = scheduler; + this.workContext = workContext; + } + + public void connect(SCAObject source) throws WiringException { + if (source instanceof Component) { + handleComponent((Component) source); + } else if (source instanceof Reference) { + handleReference((Reference) source); + } else if (source instanceof Service) { + handleService((Service) source); + } else { + throw new AssertionError("Invalid source type"); + } + } + + public void connect(InboundWire sourceWire, OutboundWire targetWire, boolean optimizable) + throws WiringException { + Map, OutboundInvocationChain> targetChains = targetWire.getInvocationChains(); + if (sourceWire.getContainer() != null && sourceWire.getContainer().isSystem()) { + sourceWire.setTargetWire(targetWire); + // system services do not need to have their chains processed, return + return; + } + for (InboundInvocationChain inboundChain : sourceWire.getInvocationChains().values()) { + // match invocation chains + OutboundInvocationChain outboundChain = targetChains.get(inboundChain.getOperation()); + if (outboundChain == null) { + throw new IncompatibleInterfacesException(sourceWire, targetWire); + } + connect(inboundChain, outboundChain); + } + if (postProcessorRegistry != null) { + // run wire post-processors + postProcessorRegistry.process(sourceWire, targetWire); + } + if (optimizable && WireUtils.isOptimizable(sourceWire) && WireUtils.isOptimizable(targetWire)) { + sourceWire.setOptimizable(true); + sourceWire.setTargetWire(targetWire); + } + } + + /** + * Connects the source outbound wire to a corresponding target inbound wire + * + * @param sourceWire the source wire to connect + * @param targetWire the target wire to connect to + * @param optimizable true if the wire connection can be optimized + * @throws WiringException + */ + public void connect(OutboundWire sourceWire, InboundWire targetWire, boolean optimizable) + throws WiringException { + SCAObject source = sourceWire.getContainer(); + assert source != null; + SCAObject target = targetWire.getContainer(); + assert target != null; + Map, InboundInvocationChain> targetChains = targetWire.getInvocationChains(); + if (sourceWire.getContainer() != null && sourceWire.getContainer().isSystem()) { + sourceWire.setTargetWire(targetWire); + // system services do not need to have their chains processed, return + return; + } + + // FIXME: [rfeng] The targetWire is provided by the system + if (targetWire.getContainer() != null && targetWire.getContainer().isSystem()) { + sourceWire.setOptimizable(true); + sourceWire.setTargetWire(targetWire); + // system services do not need to have their chains processed, return + return; + } + + // match outbound to inbound chains + for (OutboundInvocationChain outboundChain : sourceWire.getInvocationChains().values()) { + Operation operation = outboundChain.getOperation(); + + // TODO: TUSCANY-1111, can't use targetChains.get with different IDLs so use simple name matching + // InboundInvocationChain inboundChain = targetChains.get(operation); + InboundInvocationChain inboundChain = null; // = targetChains.get(operation); + for (InboundInvocationChain ic: targetChains.values()) { + if (ic.getOperation().equals(operation)) { + inboundChain = ic; + break; + } + } + if (inboundChain == null) { + throw new IncompatibleInterfacesException(sourceWire, targetWire); + } + Operation inboundOperation = inboundChain.getOperation(); + boolean isOneWayOperation = operation.isNonBlocking(); + TargetInvoker invoker; + if (target instanceof Component) { + Component component = (Component) target; + QualifiedName wireTargetName = sourceWire.getTargetName(); + String portName = null; + if (wireTargetName != null) { + portName = wireTargetName.getPortName(); + } + try { + invoker = component.createTargetInvoker(portName, inboundOperation, targetWire); + } catch (TargetInvokerCreationException e) { + throw new WireConnectException("Error connecting source and target", sourceWire, targetWire, e); + } + } else if (target instanceof ReferenceBinding) { + ReferenceBinding referenceBinding = (ReferenceBinding) target; + try { + invoker = referenceBinding.createTargetInvoker(targetWire.getServiceContract(), inboundOperation); + } catch (TargetInvokerCreationException e) { + String targetName = targetWire.getContainer().getName(); + throw new WireConnectException("Error processing inbound wire", null, null, targetName, null, e); + } + } else if (target instanceof ServiceBinding) { + ServiceBinding binding = (ServiceBinding) target; + try { + invoker = binding.createTargetInvoker(targetWire.getServiceContract(), inboundChain.getOperation()); + } catch (TargetInvokerCreationException e) { + String targetName = targetWire.getContainer().getName(); + throw new WireConnectException("Error processing inbound wire", null, null, targetName, null, e); + } + } else { + throw new AssertionError(); + } + + if (source instanceof ServiceBinding) { + // services are a special case: invoker must go on the inbound and outbound chains + if (target instanceof Component && isOneWayOperation) { + // if the target is a component and the operation is non-blocking + connect(outboundChain, inboundChain, invoker, true); + } else { + connect(outboundChain, inboundChain, invoker, false); + } + ServiceBinding binding = (ServiceBinding) source; + InboundInvocationChain chain = binding.getInboundWire().getInvocationChains().get(operation); + chain.setTargetInvoker(invoker); + } else { + if (target instanceof Component && isOneWayOperation) { + // if the target is a component and the operation is non-blocking + connect(outboundChain, inboundChain, invoker, true); + } else { + connect(outboundChain, inboundChain, invoker, false); + } + } + } + + // create source callback chains and connect them if target callback chains exist + Map, OutboundInvocationChain> sourceCallbackChains = + targetWire.getSourceCallbackInvocationChains(source.getName()); + for (InboundInvocationChain inboundChain : sourceWire.getTargetCallbackInvocationChains().values()) { + Operation operation = inboundChain.getOperation(); + if (sourceCallbackChains != null && sourceCallbackChains.get(operation) != null) { + String opName = operation.getName(); + throw new IllegalCallbackException("Source callback chain should not exist for operation", + opName, + sourceWire, + targetWire); + } + + ServiceContract targetContract = targetWire.getServiceContract(); + assert targetContract != null; + String opName = operation.getName(); + assert opName != null; + Operation targetOp = targetContract.getCallbackOperations().get(opName); + OutboundInvocationChain outboundChain = wireService.createOutboundChain(targetOp); + targetWire.addSourceCallbackInvocationChain(source.getName(), targetOp, outboundChain); + if (source instanceof Component) { + Component component = (Component) source; + TargetInvoker invoker; + try { + invoker = component.createTargetInvoker(targetOp.getName(), operation, null); + } catch (TargetInvokerCreationException e) { + throw new WireConnectException("Error connecting source and target", sourceWire, targetWire, e); + } + boolean isOneWayOperation = targetOp.isNonBlocking(); + if (target instanceof Component && isOneWayOperation) { + // if the target is a component and the operation is non-blocking + connect(outboundChain, inboundChain, invoker, true); + } else { + connect(outboundChain, inboundChain, invoker, false); + } + } else if (source instanceof ReferenceBinding) { + ReferenceBinding binding = (ReferenceBinding) source; + ServiceContract sourceContract = sourceWire.getServiceContract(); + TargetInvoker invoker; + try { + invoker = binding.createTargetInvoker(sourceContract, operation); + } catch (TargetInvokerCreationException e) { + throw new WireConnectException("Error connecting source and target", sourceWire, targetWire, e); + } + connect(outboundChain, inboundChain, invoker, false); + } else if (source instanceof ServiceBinding) { + ServiceBinding binding = (ServiceBinding) source; + ServiceContract sourceContract = sourceWire.getServiceContract(); + TargetInvoker invoker; + try { + invoker = binding.createTargetInvoker(sourceContract, operation); + } catch (TargetInvokerCreationException e) { + String targetName = sourceWire.getContainer().getName(); + throw new WireConnectException("Error processing callback wire", null, null, targetName, null, e); + } + connect(outboundChain, inboundChain, invoker, false); + } else { + throw new AssertionError(); + } + } + if (postProcessorRegistry != null) { + // run wire post-processors + postProcessorRegistry.process(sourceWire, targetWire); + } + // perform optimization, if possible + if (optimizable && WireUtils.isOptimizable(sourceWire) && WireUtils.isOptimizable(targetWire)) { + sourceWire.setOptimizable(true); + sourceWire.setTargetWire(targetWire); + } + } + + /** + * Connects a source to target chain + * + * @param sourceChain the source chain + * @param targetChain the target chain + * @param invoker the invoker to place on the source chain for dispatching invocations + * @param nonBlocking true if the operation is non-blocking + */ + protected void connect(OutboundInvocationChain sourceChain, + InboundInvocationChain targetChain, + TargetInvoker invoker, + boolean nonBlocking) throws WireConnectException { + Interceptor head = targetChain.getHeadInterceptor(); + if (head == null) { + throw new WireConnectException("Inbound chain must contain at least one interceptor"); + } + if (nonBlocking) { + sourceChain.setTargetInterceptor(new NonBlockingBridgingInterceptor(scheduler, workContext, head)); + } else { + sourceChain.setTargetInterceptor(new SynchronousBridgingInterceptor(head)); + } + sourceChain.prepare(); + sourceChain.setTargetInvoker(invoker); + } + + + /** + * Connects an inbound source chain to an outbound target chain + * + * @param sourceChain the source chain to connect + * @param targetChain the target chain to connect + */ + protected void connect(InboundInvocationChain sourceChain, OutboundInvocationChain targetChain) + throws WireConnectException { + Interceptor head = targetChain.getHeadInterceptor(); + if (head == null) { + throw new WireConnectException("Outbound chain must contain at least one interceptor"); + } + // invocations from inbound to outbound chains are always synchronous as they occur in services and references + sourceChain.addInterceptor(new SynchronousBridgingInterceptor(head)); + } + + /** + * Connects an outbound wire to its target in a composite. + * + * @param sourceWire the source wire to connect + * @throws WiringException + */ + protected void connect(SCAObject source, OutboundWire sourceWire, SCAObject target) throws WiringException { + assert sourceWire.getTargetName() != null; + QualifiedName targetName = sourceWire.getTargetName(); + if (target instanceof Component) { + connect(source, sourceWire, (Component) target); + } else if (target instanceof Reference) { + connect(source, sourceWire, (Reference) target); + } else if (target instanceof Service) { + connect(source, sourceWire, (Service) target); + } else if (target == null) { + String sourceName = sourceWire.getContainer().getName(); + String sourceReference = sourceWire.getReferenceName(); + throw new TargetServiceNotFoundException("Target service not found", + sourceName, + sourceReference, + targetName.getPartName(), + targetName.getPortName()); + } else { + String sourceName = sourceWire.getContainer().getName(); + String sourceRef = sourceWire.getReferenceName(); + String partName = targetName.getPartName(); + String portName = targetName.getPortName(); + throw new InvalidTargetTypeException("Invalid target type", sourceName, sourceRef, partName, portName); + } + } + + protected void connect(SCAObject source, OutboundWire sourceWire, Reference target) throws WiringException { + assert sourceWire.getTargetName() != null; + QualifiedName targetName = sourceWire.getTargetName(); + InboundWire targetWire = null; + for (ReferenceBinding binding : target.getReferenceBindings()) { + InboundWire candidate = binding.getInboundWire(); + if (sourceWire.getBindingType().equals(candidate.getBindingType())) { + targetWire = candidate; + break; + } + } + if (targetWire == null) { + if (target.getReferenceBindings().size() > 0 && source instanceof Component) { + // TODO create a pluggable algorithm for selecting the binding type + targetWire = target.getReferenceBindings().get(0).getInboundWire(); + } + if (targetWire == null) { + throw new NoCompatibleBindingsException(source.getName(), + targetName.getPartName(), + targetName.getPortName()); + } + } + checkIfWireable(sourceWire, targetWire); + boolean optimizable = isOptimizable(source.getScope(), target.getScope()); + connect(sourceWire, targetWire, optimizable); + } + + protected void connect(SCAObject source, OutboundWire sourceWire, Service target) throws WiringException { + assert sourceWire.getTargetName() != null; + QualifiedName targetName = sourceWire.getTargetName(); + InboundWire targetWire = null; + for (ServiceBinding binding : target.getServiceBindings()) { + InboundWire candidate = binding.getInboundWire(); + if (sourceWire.getBindingType().equals(candidate.getBindingType())) { + targetWire = candidate; + break; + } + } + if (targetWire == null) { + throw new NoCompatibleBindingsException(source.getName(), + targetName.getPartName(), + targetName.getPortName()); + } + checkIfWireable(sourceWire, targetWire); + boolean optimizable = isOptimizable(source.getScope(), target.getScope()); + connect(sourceWire, targetWire, optimizable); + } + + protected void connect(SCAObject source, OutboundWire sourceWire, Component target) + throws WiringException { + assert sourceWire.getTargetName() != null; + QualifiedName targetName = sourceWire.getTargetName(); + InboundWire targetWire; + // FIXME JFM should we move getInboundSystemWire up to Component? + if (target instanceof CompositeComponent && source.isSystem()) { + targetWire = ((CompositeComponent) target).getInboundSystemWire(targetName.getPortName()); + } else { + targetWire = target.getInboundWire(targetName.getPortName()); + } + if (targetWire == null) { + String sourceName = sourceWire.getContainer().getName(); + String sourceReference = sourceWire.getReferenceName(); + throw new TargetServiceNotFoundException("Target service does not exist or is not configured with a " + + "local binding", + sourceName, + sourceReference, + targetName.getPartName(), + targetName.getPortName()); + } + checkIfWireable(sourceWire, targetWire); + boolean optimizable = isOptimizable(source.getScope(), target.getScope()); + connect(sourceWire, targetWire, optimizable); + } + + protected void autowire(OutboundWire outboundWire, CompositeComponent parent) + throws WiringException { + // JFM FIXME test coverage for this method + InboundWire targetWire; + try { + Class interfaze = outboundWire.getServiceContract().getInterfaceClass(); + if (CompositeComponent.class.equals(interfaze)) { + JavaServiceContract contract = new JavaServiceContract(CompositeComponent.class); + targetWire = new LoopBackWire(); + targetWire.setServiceContract(contract); + targetWire.setContainer(parent); + outboundWire.setTargetWire(targetWire); + return; + } + if (outboundWire.getContainer().isSystem()) { + targetWire = parent.resolveSystemAutowire(interfaze); + } else { + targetWire = parent.resolveAutowire(interfaze); + } + } catch (TargetResolutionException e) { + String sourceReference = outboundWire.getReferenceName(); + String sourceName = outboundWire.getContainer().getName(); + throw new WireConnectException("Error resolving autowire target", + sourceName, + sourceReference, + null, + null, + e); + } + if (targetWire == null) { + // autowire may return null if it is optional. The client must decide if an error should be thrown + return; + } + Scope sourceScope = outboundWire.getContainer().getScope(); + Scope targetScope = targetWire.getContainer().getScope(); + boolean optimizable = isOptimizable(sourceScope, targetScope); + connect(outboundWire, targetWire, optimizable); + } + + protected void checkIfWireable(OutboundWire sourceWire, InboundWire targetWire) + throws IncompatibleInterfacesException { + if (wireService == null) { + Class sourceInterface = sourceWire.getServiceContract().getInterfaceClass(); + Class targetInterface = targetWire.getServiceContract().getInterfaceClass(); + if (!sourceInterface.isAssignableFrom(targetInterface)) { + throw new IncompatibleInterfacesException(sourceWire, targetWire); + } + } else { + try { + ServiceContract sourceContract = sourceWire.getServiceContract(); + ServiceContract targetContract = targetWire.getServiceContract(); + wireService.checkCompatibility(sourceContract, targetContract, false); + } catch (IncompatibleServiceContractException e) { + throw new IncompatibleInterfacesException(sourceWire, targetWire, e); + } + } + } + + protected boolean isOptimizable(Scope pReferrer, Scope pReferee) { + if (pReferrer == Scope.UNDEFINED + || pReferee == Scope.UNDEFINED + || pReferrer == Scope.CONVERSATION + || pReferee == Scope.CONVERSATION) { + return false; + } + if (pReferee == pReferrer) { + return true; + } else if (pReferrer == Scope.STATELESS) { + return true; + } else if (pReferee == Scope.STATELESS) { + return false; + } else if (pReferrer == Scope.REQUEST && pReferee == Scope.SESSION) { + return true; + } else if (pReferrer == Scope.REQUEST && pReferee == Scope.COMPOSITE) { + return true; + } else if (pReferrer == Scope.REQUEST && pReferee == Scope.SYSTEM) { + return true; + } else if (pReferrer == Scope.SESSION && pReferee == Scope.COMPOSITE) { + return true; + } else if (pReferrer == Scope.SESSION && pReferee == Scope.SYSTEM) { + return true; + } else //noinspection SimplifiableIfStatement + if (pReferrer == Scope.SYSTEM && pReferee == Scope.COMPOSITE) { + // case where a service context points to a composite scoped component + return true; + } else { + return pReferrer == Scope.COMPOSITE && pReferee == Scope.SYSTEM; + } + } + + /** + * Connects wires from a service to a target + * + * @param service the service + * @throws WiringException if an exception connecting the service wires is encountered + */ + private void handleService(Service service) throws WiringException { + CompositeComponent parent = service.getParent(); + assert parent != null; + for (ServiceBinding binding : service.getServiceBindings()) { + InboundWire inboundWire = binding.getInboundWire(); + OutboundWire outboundWire = binding.getOutboundWire(); + // For a composite reference only, since its outbound wire comes from its parent composite, + // the corresponding target would not lie in its parent but rather in its parent's parent + SCAObject target; + if (service.isSystem()) { + target = parent.getSystemChild(outboundWire.getTargetName().getPartName()); + } else { + target = parent.getChild(outboundWire.getTargetName().getPartName()); + } + // connect the outbound service wire to the target + connect(binding, outboundWire, target); + // NB: this connect must be done after the outbound service chain is connected to its target above + connect(inboundWire, outboundWire, true); + } + } + + private void handleReference(Reference reference) throws WiringException { + CompositeComponent parent = reference.getParent(); + assert parent != null; + for (ReferenceBinding binding : reference.getReferenceBindings()) { + InboundWire inboundWire = binding.getInboundWire(); + Map, InboundInvocationChain> inboundChains = inboundWire.getInvocationChains(); + for (InboundInvocationChain chain : inboundChains.values()) { + // add target invoker on inbound side + ServiceContract contract = inboundWire.getServiceContract(); + Operation operation = chain.getOperation(); + TargetInvoker invoker; + try { + invoker = binding.createTargetInvoker(contract, operation); + } catch (TargetInvokerCreationException e) { + String targetName = inboundWire.getContainer().getName(); + throw new WireConnectException("Error processing inbound wire", + null, + null, + targetName, + null, + e); + } + chain.setTargetInvoker(invoker); + chain.prepare(); + } + OutboundWire outboundWire = binding.getOutboundWire(); + // connect the reference's inbound and outbound wires + connect(inboundWire, outboundWire, true); + } + } + + private void handleComponent(Component component) throws WiringException { + CompositeComponent parent = component.getParent(); + assert parent != null; + // connect outbound wires for component references to their targets + for (List referenceWires : component.getOutboundWires().values()) { + for (OutboundWire outboundWire : referenceWires) { + try { + if (component.isSystem()) { + if (outboundWire.isAutowire()) { + autowire(outboundWire, parent); + + } else { + SCAObject target = parent.getSystemChild(outboundWire.getTargetName().getPartName()); + connect(component, outboundWire, target); + } + } else { + if (outboundWire.isAutowire()) { + autowire(outboundWire, parent); + } else { + if (outboundWire.getTargetName() == null) { + String referenceName = outboundWire.getReferenceName(); + throw new MissingWireTargetException("Target name was null", referenceName); + } + SCAObject target = parent.getChild(outboundWire.getTargetName().getPartName()); + connect(component, outboundWire, target); + } + } + } catch (WiringException e) { + e.addContextName(component.getName()); + e.addContextName(parent.getName()); + throw e; + } + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java new file mode 100644 index 0000000000..5ca843e198 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IllegalCallbackException.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WiringException; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Denotes an illegal callback + * + * @version $Rev$ $Date$ + */ +public class IllegalCallbackException extends WiringException { + + public IllegalCallbackException(String message, + String identifier, + String sourceName, + String referenceName, + String targetName, + String serviceName) { + super(message, identifier); + setSourceName(sourceName); + setReferenceName(referenceName); + setTargetName(targetName); + setTargetServiceName(serviceName); + } + + + public IllegalCallbackException(String message, String identifier, OutboundWire source, InboundWire target) { + super(message, identifier); + setSourceName(source.getContainer().getName()); + setReferenceName(source.getReferenceName()); + setTargetName(target.getContainer().getName()); + setTargetServiceName(target.getServiceName()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java new file mode 100644 index 0000000000..4b94983c34 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/IncompatibleInterfacesException.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WiringException; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Denotes an attempt to wire incompatible interfaces + * + * @version $Rev$ $Date$ + */ +public class IncompatibleInterfacesException extends WiringException { + + + public IncompatibleInterfacesException(String message, + String sourceName, + String referenceName, + String targetName, + String targetServiceName) { + super(message); + setSourceName(sourceName); + setReferenceName(referenceName); + setTargetName(targetName); + setTargetServiceName(targetServiceName); + } + + public IncompatibleInterfacesException(String message, String sourceName, + String referenceName, + String targetName, + String serviceName, + Throwable cause) { + super(message, cause); + setSourceName(sourceName); + setReferenceName(referenceName); + setTargetName(targetName); + setTargetServiceName(serviceName); + } + + public IncompatibleInterfacesException(InboundWire source, OutboundWire target) { + super("Incompatible source and target interfaces"); + setTargetServiceName(source.getServiceName()); + if (source.getContainer() != null) { + setSourceName(source.getContainer().getName()); + } + setReferenceName(target.getReferenceName()); + if (target.getContainer() != null) { + setTargetName(target.getContainer().getName()); + } + } + + public IncompatibleInterfacesException(OutboundWire source, InboundWire target) { + super("Incompatible source and target interfaces"); + setTargetServiceName(target.getServiceName()); + if (source.getContainer() != null) { + setSourceName(source.getContainer().getName()); + } + setReferenceName(source.getReferenceName()); + if (target.getContainer() != null) { + setTargetName(target.getContainer().getName()); + } + } + + public IncompatibleInterfacesException(OutboundWire source, InboundWire target, Throwable throwable) { + super("Incompatible source and target interfaces", throwable); + setTargetServiceName(target.getServiceName()); + if (source.getContainer() != null) { + setSourceName(source.getContainer().getName()); + } + setReferenceName(source.getReferenceName()); + if (target.getContainer() != null) { + setTargetName(target.getContainer().getName()); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java new file mode 100644 index 0000000000..e96fb764a0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/InvalidTargetTypeException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WiringException; + +/** + * Denotes an invalid target service for a wire + * + * @version $Rev$ $Date$ + */ +public class InvalidTargetTypeException extends WiringException { + + public InvalidTargetTypeException(String message, + String sourceName, + String referenceName, + String targetName, + String serviceName) { + super(message); + setSourceName(sourceName); + setReferenceName(referenceName); + setTargetName(targetName); + setTargetServiceName(serviceName); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java new file mode 100644 index 0000000000..620fbf6694 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoCompatibleBindingsException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WiringException; + +/** + * @version $Rev$ $Date$ + */ +public class NoCompatibleBindingsException extends WiringException { + public NoCompatibleBindingsException(String sourceName, + String targetName, + String serviceName) { + super("No compatible bindings for source and target"); + setSourceName(sourceName); + setTargetName(targetName); + setTargetServiceName(serviceName); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java new file mode 100644 index 0000000000..71eb9ebd26 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoConversationalContractException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.BuilderException; + +/** + * Raised when a component has conversational scope but no conversational contract + * + * @version $Rev: 487877 $ $Date: 2006-12-16 15:32:16 -0500 (Sat, 16 Dec 2006) $ + */ +public class NoConversationalContractException extends BuilderException { + + public NoConversationalContractException(String message, String identifier) { + super(message, identifier); + } + + public NoConversationalContractException(String message) { + super(message); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java new file mode 100644 index 0000000000..340a20f239 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/NoRegisteredBuilderException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.BuilderException; + +/** + * Raised when a builder cannot be found for a SCDL entry type + * + * @version $Rev$ $Date$ + */ +public class NoRegisteredBuilderException extends BuilderException { + + public NoRegisteredBuilderException(String message, String identifier) { + super(message, identifier); + } + + public NoRegisteredBuilderException(String message) { + super(message); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java new file mode 100644 index 0000000000..873bf619b0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/TargetServiceNotFoundException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WiringException; + +/** + * Indicates the target service of a reference was not found + * + * @version $Rev$ $Date$ + */ +public class TargetServiceNotFoundException extends WiringException { + + public TargetServiceNotFoundException(String message, + String sourceName, + String referenceName, + String targetName, + String serviceName) { + super(message); + setSourceName(sourceName); + setReferenceName(referenceName); + setTargetName(targetName); + setTargetServiceName(serviceName); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java new file mode 100644 index 0000000000..89105d27b4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WireConnectException.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WiringException; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Denotes a general error connecting two wires + * + * @version $Rev$ $Date$ + */ +public class WireConnectException extends WiringException { + + public WireConnectException(String message) { + super(message); + } + + public WireConnectException(String message, + String sourceName, + String referenceName, + String targetName, + String serviceName, + Throwable throwable) { + super(message, throwable); + setSourceName(sourceName); + setReferenceName(referenceName); + setTargetName(targetName); + setTargetServiceName(serviceName); + } + + + public WireConnectException(String message, OutboundWire source, InboundWire target, Throwable throwable) { + super(message, throwable); + setSourceName(source.getContainer().getName()); + setReferenceName(source.getReferenceName()); + setTargetName(target.getContainer().getName()); + setTargetServiceName(target.getServiceName()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java new file mode 100644 index 0000000000..3bc617066a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.wire.WirePostProcessor; +import org.apache.tuscany.spi.wire.WirePostProcessorRegistry; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * The default implementation of a WirePostProcessor + * + * @version $Rev$ $Date$ + */ +public class WirePostProcessorRegistryImpl implements WirePostProcessorRegistry { + + private final List processors = new ArrayList(); + + public void process(OutboundWire source, InboundWire target) { + for (WirePostProcessor processor : processors) { + processor.process(source, target); + } + } + + public void process(InboundWire source, OutboundWire target) { + for (WirePostProcessor processor : processors) { + processor.process(source, target); + } + } + + public void register(WirePostProcessor processor) { + processors.add(processor); + } + + public void unregister(WirePostProcessor processor) { + processors.remove(processor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java new file mode 100644 index 0000000000..16cf27048a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WiringExceptionFormatter.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.io.PrintWriter; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.WiringException; + +import org.apache.tuscany.host.monitor.ExceptionFormatter; +import org.apache.tuscany.host.monitor.FormatterRegistry; + +/** + * Formats {@link WiringException}s + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class WiringExceptionFormatter implements ExceptionFormatter { + private FormatterRegistry factory; + + public WiringExceptionFormatter(@Autowire FormatterRegistry factory) { + this.factory = factory; + factory.register(this); + } + + public boolean canFormat(Class type) { + return WiringException.class.isAssignableFrom(type); + } + + @Destroy + public void destroy() { + factory.unregister(this); + } + + public PrintWriter write(PrintWriter writer, Throwable exception) { + assert exception instanceof WiringException; + WiringException e = (WiringException) exception; + e.appendBaseMessage(writer); + if (e.getSourceName() != null && e.getReferenceName() != null) { + writer.write("\nSource : " + e.getSourceName() + "/" + e.getReferenceName()); + } else if (e.getSourceName() != null) { + writer.write("\nSource : " + e.getSourceName()); + } + if (e.getTargetName() != null && e.getTargetServiceName() != null) { + writer.write("\nTarget : " + e.getTargetName() + "/" + e.getTargetServiceName()); + } else if (e.getTargetName() != null) { + writer.write("\nTarget : " + e.getTargetName()); + } + e.appendContextStack(writer).append("\n"); + return writer; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.java new file mode 100644 index 0000000000..6cc06d7646 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentContextImpl.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.core.component; + +import java.net.URI; + +import org.osoa.sca.CallableReference; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.CompositeContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +import org.apache.tuscany.api.TuscanyRuntimeException; +import org.apache.tuscany.spi.component.Component; + +/** + * + * @version $Rev$ $Date$ + */ +public class ComponentContextImpl implements ComponentContext { + private final CompositeContext context; + private final Component component; + + public ComponentContextImpl(CompositeContext context, Component component) { + this.component = component; + this.context = context; + } + + public String getURI() { + try { + return component.getName(); + } catch (TuscanyRuntimeException e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + public > R cast(B target) throws IllegalArgumentException { + throw new UnsupportedOperationException(); + } + + public B getService(Class businessInterface, String referenceName) { + try { + return context.locateService(businessInterface, component.getName() + "/" + referenceName); + } catch (TuscanyRuntimeException e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + public ServiceReference getServiceReference(Class businessInterface, String referenceName) { + throw new UnsupportedOperationException(); + } + + public B getProperty(Class type, String propertyName) { + throw new UnsupportedOperationException(); + } + + public ServiceReference createSelfReference(Class businessInterface) { + return null; + } + + public ServiceReference createSelfReference(Class businessInterface, String serviceName) { + return null; + } + + public RequestContext getRequestContext() { + return context.getRequestContext(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java new file mode 100644 index 0000000000..35125b85ef --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component; + +/** + * Implementations enable lazy retrieval of a scope id associated with a request, i.e. an id (and presumably a context) + * do not have to be generated if the scope is never accessed. Identifiers are associated with the current request + * thread and keyed on scope type. + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.spi.component.WorkContext + */ +public interface ScopeIdentifier { + + /** + * Returns the scope id for the request. + */ + Object getIdentifier(); +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java new file mode 100644 index 0000000000..8d2afc35d9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component; + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.WorkContext; + +/** + * An implementation of an {@link org.apache.tuscany.spi.component.WorkContext} that handles event-to-thread + * associations using an InheritableThreadLocal + * + * @version $Rev$ $Date$ + */ +public class WorkContextImpl implements WorkContext { + private static final Object REMOTE_CONTEXT = new Object(); + private static final Object CORRELATION_ID = new Object(); + private static final Object CALLBACK_ROUTING_CHAIN = new Object(); + private static final Object CURRENT_ATOMIC = new Object(); + private static final Object CURRENT_SERVICE_NAMES = new Object(); + + // [rfeng] We cannot use InheritableThreadLocal for message ids here since it's shared by parent and children + private ThreadLocal> workContext = new ThreadLocal>(); + + // [rfeng] Session id requires InheritableThreadLocal + private ThreadLocal> inheritableContext = new InheritableThreadLocal>(); + + public WorkContextImpl() { + super(); + } + + public Object getCurrentCorrelationId() { + Map map = workContext.get(); + if (map == null) { + return null; + } + return map.get(CORRELATION_ID); + } + + public void setCurrentCorrelationId(Object correlationId) { + Map map = getWorkContextMap(); + map.put(CORRELATION_ID, correlationId); + } + + public AtomicComponent getCurrentAtomicComponent() { + Map map = workContext.get(); + if (map == null) { + return null; + } + return (AtomicComponent) map.get(CURRENT_ATOMIC); + } + + public void setCurrentAtomicComponent(AtomicComponent component) { + Map map = getWorkContextMap(); + map.put(CURRENT_ATOMIC, component); + } + + @SuppressWarnings("unchecked") + public LinkedList getCurrentCallbackRoutingChain() { + Map map = workContext.get(); + if (map == null) { + return null; + } + return (LinkedList) map.get(CALLBACK_ROUTING_CHAIN); + } + + public void setCurrentCallbackRoutingChain(LinkedList callbackRoutingChain) { + Map map = getWorkContextMap(); + map.put(CALLBACK_ROUTING_CHAIN, callbackRoutingChain); + } + + public CompositeComponent getRemoteComponent() { + Map map = workContext.get(); + if (map == null) { + return null; + } + return (CompositeComponent) map.get(REMOTE_CONTEXT); + } + + + public void setRemoteComponent(CompositeComponent component) { + Map map = getWorkContextMap(); + map.put(REMOTE_CONTEXT, component); + } + + public Object getIdentifier(Object type) { + Map map = inheritableContext.get(); + if (map == null) { + return null; + } + Object currentId = map.get(type); + if (currentId instanceof ScopeIdentifier) { + currentId = ((ScopeIdentifier) currentId).getIdentifier(); + // once we have accessed the id, replace the lazy wrapper + map.put(type, currentId); + } + return currentId; + } + + public void setIdentifier(Object type, Object identifier) { + Map map = inheritableContext.get(); + if (map == null) { + map = new IdentityHashMap(); + inheritableContext.set(map); + } + map.put(type, identifier); + } + + public void clearIdentifier(Object type) { + if (type == null) { + return; + } + Map map = inheritableContext.get(); + if (map != null) { + map.remove(type); + } + } + + public void clearIdentifiers() { + inheritableContext.remove(); + } + + @SuppressWarnings({"unchecked"}) + public String popServiceName() { + Map map = inheritableContext.get(); + if (map == null) { + return null; + } + List stack = (List) map.get(CURRENT_SERVICE_NAMES); + if (stack == null || stack.size() < 1) { + return null; + } + String name = stack.remove(stack.size() - 1); + if (stack.size() == 0) { + // cleanup to avoid leaks + map.remove(CURRENT_SERVICE_NAMES); + } + return name; + } + + @SuppressWarnings({"unchecked"}) + public String getCurrentServiceName() { + Map map = inheritableContext.get(); + if (map == null) { + return null; + } + List stack = (List) map.get(CURRENT_SERVICE_NAMES); + if (stack == null || stack.size() < 1) { + return null; + } + return stack.get(stack.size() - 1); + } + + @SuppressWarnings({"unchecked"}) + public void pushServiceName(String name) { + Map map = inheritableContext.get(); + List names; + if (map == null) { + map = new IdentityHashMap(); + inheritableContext.set(map); + names = new ArrayList(); + map.put(CURRENT_SERVICE_NAMES, names); + } else { + names = (List) map.get(CURRENT_SERVICE_NAMES); + if (names == null) { + names = new ArrayList(); + map.put(CURRENT_SERVICE_NAMES, names); + } + } + names.add(name); + } + + public void clearServiceNames() { + Map map = inheritableContext.get(); + if (map == null) { + return; + } + map.remove(CURRENT_SERVICE_NAMES); + } + + private Map getWorkContextMap() { + Map map = workContext.get(); + if (map == null) { + map = new IdentityHashMap(); + workContext.set(map); + } + return map; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java new file mode 100644 index 0000000000..6d026ca08c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +import org.apache.tuscany.spi.event.Event; + +/** + * A basic implementation of a runtime event + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class AbstractEvent implements Event { + protected Object source; + + public AbstractEvent(Object source) { + assert source != null : "Source id was null"; + this.source = source; + } + + public Object getSource() { + return source; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java new file mode 100644 index 0000000000..762b917600 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Base implementation of a request event + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class AbstractRequestEvent extends AbstractEvent implements RequestEvent { + + /** + * Creates a new event + * + * @param source the source of the event + */ + public AbstractRequestEvent(Object source) { + super(source); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java new file mode 100644 index 0000000000..ce058404da --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.event.Event; + +/** + * Implemented by runtime events associated with a composite, e.g. lifecycle events + * + * @version $$Rev$$ $$Date$$ + */ +public interface CompositeEvent extends Event { + + CompositeComponent getComposite(); + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java new file mode 100644 index 0000000000..fba36feaf6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; + +/** + * Propagated when a composite starts + * + * @version $$Rev$$ $$Date$$ + */ +public class CompositeStart extends AbstractEvent implements CompositeEvent { + + private CompositeComponent component; + + /** + * Creates a composite stop event + * + * @param source the source of the event + * @param component the composite component associated the composite being stopped + */ + public CompositeStart(Object source, CompositeComponent component) { + super(source); + this.component = component; + } + + public CompositeComponent getComposite() { + return component; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java new file mode 100644 index 0000000000..6b3e37f619 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; + +/** + * Propagated when a composite stops + * + * @version $$Rev$$ $$Date$$ + */ +public class CompositeStop extends AbstractEvent implements CompositeEvent { + + private CompositeComponent component; + + /** + * Creates a composite stop event + * + * @param source the source of the event + * @param component the composite component associated the composite being stopped + */ + public CompositeStop(Object source, CompositeComponent component) { + super(source); + this.component = component; + } + + public CompositeComponent getComposite() { + return component; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java new file mode 100644 index 0000000000..4a51d970c3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationEnd.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when a conversation session is expired + * + * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$ + */ +public class ConversationEnd extends ConversationalEvent { + + public ConversationEnd(Object source, Object id) { + super(source, id); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java new file mode 100644 index 0000000000..5725369bf6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationStart.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when a conversation session has started + * + * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$ + */ +public class ConversationStart extends ConversationalEvent { + + public ConversationStart(Object source, Object id) { + super(source, id); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java new file mode 100644 index 0000000000..a75086e745 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/ConversationalEvent.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * A base implementation of conversational session events in the runtime + * + * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$ + */ +public class ConversationalEvent extends AbstractEvent { + + private Object id; + + public ConversationalEvent(Object source, Object id) { + super(source); + assert id != null : "Conversation id was null"; + this.id = id; + } + + public Object getId() { + return id; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java new file mode 100644 index 0000000000..01bd769031 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when an HTTP-based request has ended. + * + * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$ + */ +public class HttpRequestEnded extends HttpSessionEvent { + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpRequestEnded(Object source, Object id) { + super(source, id); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java new file mode 100644 index 0000000000..9d0ff80dd7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when an HTTP-based request has started + * + * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$ + */ +public class HttpRequestStart extends HttpSessionEvent { + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpRequestStart(Object source, Object id) { + super(source, id); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java new file mode 100644 index 0000000000..7f2bebe94a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when an HTTP-based session is expired + * + * @version $$Rev$$ $$Date$$ + */ +public class HttpSessionEnd extends HttpSessionEvent { + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpSessionEnd(Object source, Object id) { + super(source, id); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java new file mode 100644 index 0000000000..ed245d0930 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * A base implementation of HTTP-based session events in the runtime + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class HttpSessionEvent extends AbstractEvent { + + private Object id; + + public HttpSessionEvent(Object source, Object id) { + super(source); + assert id != null : "Session id was null"; + this.id = id; + } + + + public Object getSource() { + return source; + } + + public Object getId() { + return id; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java new file mode 100644 index 0000000000..7f9c0fadea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when an HTTP-based session has started + * + * @version $$Rev$$ $$Date$$ + */ +public class HttpSessionStart extends HttpSessionEvent { + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpSessionStart(Object source, Object id) { + super(source, id); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java new file mode 100644 index 0000000000..25856e86f8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when a request completes or is ended + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestEnd extends AbstractRequestEvent { + + /** + * Creates a new event + * + * @param source the source of the event + */ + public RequestEnd(Object source) { + super(source); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java new file mode 100644 index 0000000000..9a6d767236 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Implemented by runtime events associated request + * + * @version $$Rev$$ $$Date$$ + */ +public interface RequestEvent { + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java new file mode 100644 index 0000000000..466f52551a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when a request is started in the runtime + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestStart extends AbstractRequestEvent { + + /** + * Creates a new event + * + * @param source the source of the event + */ + public RequestStart(Object source) { + super(source); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java new file mode 100644 index 0000000000..cde61eaa5a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.spi.AbstractLifecycle; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.PersistenceException; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.TargetNotFoundException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.event.EventFilter; +import org.apache.tuscany.spi.event.RuntimeEventListener; +import org.apache.tuscany.spi.event.TrueFilter; + +/** + * Implements functionality common to scope contexts. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeContainer extends AbstractLifecycle implements ScopeContainer { + private static final EventFilter TRUE_FILTER = new TrueFilter(); + + protected WorkContext workContext; + protected ScopeContainerMonitor monitor; + private Map> listeners; + + public AbstractScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) { + this.workContext = workContext; + this.monitor = monitor; + } + + public void addListener(RuntimeEventListener listener) { + addListener(TRUE_FILTER, listener); + } + + public void removeListener(RuntimeEventListener listener) { + assert listener != null; + synchronized (getListeners()) { + for (List currentList : getListeners().values()) { + for (RuntimeEventListener current : currentList) { + if (current == listener) { + currentList.remove(current); + return; + } + } + } + } + } + + public void addListener(EventFilter filter, RuntimeEventListener listener) { + assert listener != null; + synchronized (getListeners()) { + List 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; + for (Map.Entry> entry : getListeners().entrySet()) { + if (entry.getKey().match(event)) { + for (RuntimeEventListener listener : entry.getValue()) { + listener.onEvent(event); + } + } + } + } + + public Object getInstance(AtomicComponent component) throws TargetResolutionException { + InstanceWrapper ctx = getInstanceWrapper(component, true); + if (ctx != null) { + if (!ctx.isStarted()) { + ctx.start(); + } + return ctx.getInstance(); + } + return null; + } + + public Object getAssociatedInstance(AtomicComponent component) throws TargetResolutionException { + InstanceWrapper ctx = getInstanceWrapper(component, false); + if (ctx != null) { + if (!ctx.isStarted()) { + ctx.start(); + } + return ctx.getInstance(); + } + throw new TargetNotFoundException(component.getName()); + } + + public void persistNew(AtomicComponent component, String id, Object instance, long expiration) + throws PersistenceException { + throw new UnsupportedOperationException("Scope does not support persistence"); + + } + + public void persist(AtomicComponent component, String id, Object instance, long expiration) + throws PersistenceException { + throw new UnsupportedOperationException("Scope does not support persistence"); + } + + public void remove(AtomicComponent component) throws PersistenceException { + throw new UnsupportedOperationException("Scope does not support persistence"); + } + + protected Map> getListeners() { + if (listeners == null) { + listeners = new ConcurrentHashMap>(); + } + return listeners; + } + + protected void checkInit() { + if (getLifecycleState() != RUNNING) { + throw new IllegalStateException("Scope container not running [" + getLifecycleState() + "]"); + } + } + + protected WorkContext getWorkContext() { + return workContext; + } + + public String toString() { + return "In state [" + super.toString() + ']'; + } + + protected abstract InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) + throws TargetResolutionException; +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java new file mode 100644 index 0000000000..21ff792282 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeContainer.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetInitializationException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; + +/** + * A scope context which manages atomic component instances keyed by composite + * + * @version $Rev$ $Date$ + */ +public class CompositeScopeContainer extends AbstractScopeContainer { + private static final InstanceWrapper EMPTY = new EmptyWrapper(); + private static final ComponentInitComparator COMPARATOR = new ComponentInitComparator(); + + private final Map instanceWrappers; + // the queue of instanceWrappers to destroy, in the order that their instances were created + private final List destroyQueue; + + public CompositeScopeContainer(ScopeContainerMonitor monitor) { + super(null, monitor); + instanceWrappers = new ConcurrentHashMap(); + destroyQueue = new ArrayList(); + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + + public void onEvent(Event event) { + checkInit(); + if (event instanceof CompositeStart) { + try { + eagerInitComponents(); + } catch (ObjectCreationException e) { + monitor.eagerInitializationError(e); + } catch (TargetResolutionException e) { + monitor.eagerInitializationError(e); + } + lifecycleState = RUNNING; + } else if (event instanceof CompositeStop) { + shutdownContexts(); + } + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + checkInit(); + instanceWrappers.clear(); + synchronized (destroyQueue) { + destroyQueue.clear(); + } + lifecycleState = STOPPED; + } + + /** + * Notifies instanceWrappers of a shutdown in reverse order to which they were started + */ + private void shutdownContexts() { + if (destroyQueue.size() == 0) { + return; + } + synchronized (destroyQueue) { + // shutdown destroyable instances in reverse instantiation order + ListIterator iter = destroyQueue.listIterator(destroyQueue.size()); + while (iter.hasPrevious()) { + try { + iter.previous().stop(); + } catch (TargetDestructionException e) { + monitor.destructionError(e); + } + } + destroyQueue.clear(); + } + } + + public void register(AtomicComponent component) { + checkInit(); + instanceWrappers.put(component, EMPTY); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) + throws TargetResolutionException { + checkInit(); + InstanceWrapper ctx = instanceWrappers.get(component); + assert ctx != null; + if (ctx == EMPTY && !create) { + return null; + } + if (ctx == EMPTY) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + instanceWrappers.put(component, ctx); + synchronized (destroyQueue) { + destroyQueue.add(ctx); + } + } + return ctx; + } + + private void eagerInitComponents() throws ObjectCreationException, TargetResolutionException { + List componentList = new ArrayList(instanceWrappers.keySet()); + Collections.sort(componentList, COMPARATOR); + // start each group + for (AtomicComponent component : componentList) { + if (component.getInitLevel() <= 0) { + // Don't eagerly init + continue; + } + // the instance could have been created from a depth-first traversal + InstanceWrapper ctx = instanceWrappers.get(component); + if (ctx == EMPTY) { + try { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + } catch (ObjectCreationException e) { + e.addContextName(component.getName()); + throw e; + } + ctx.start(); + instanceWrappers.put(component, ctx); + destroyQueue.add(ctx); + } + } + } + + private static class ComponentInitComparator implements Comparator { + public int compare(AtomicComponent o1, AtomicComponent o2) { + return o1.getInitLevel() - o2.getInitLevel(); + } + } + + private static class EmptyWrapper implements InstanceWrapper { + public Object getInstance() { + return null; + } + + public boolean isStarted() { + return true; + } + + public void start() throws TargetInitializationException { + + } + + public void stop() throws TargetDestructionException { + + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java new file mode 100644 index 0000000000..a761f05d4b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/CompositeScopeObjectFactory.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.api.annotation.Monitor; + +/** + * Creates a new composite scope context + * + * @version $$Rev$$ $$Date$$ + */ +@EagerInit +public class CompositeScopeObjectFactory implements ObjectFactory { + private ScopeContainerMonitor monitor; + + public CompositeScopeObjectFactory(@Autowire ScopeRegistry registry, + @Monitor ScopeContainerMonitor monitor) { + registry.registerFactory(Scope.COMPOSITE, this); + this.monitor = monitor; + } + + public CompositeScopeContainer getInstance() throws ObjectCreationException { + return new CompositeScopeContainer(monitor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java new file mode 100644 index 0000000000..1a77f3ecb3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeContainer.java @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.PersistenceException; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetNotFoundException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.event.RuntimeEventListener; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.services.store.Store; +import org.apache.tuscany.spi.services.store.StoreExpirationEvent; +import org.apache.tuscany.spi.services.store.StoreReadException; +import org.apache.tuscany.spi.services.store.StoreWriteException; + +/** + * A scope context which manages atomic component instances keyed on a conversation session + * + * @version $Rev: 452655 $ $Date: 2006-10-03 18:09:02 -0400 (Tue, 03 Oct 2006) $ + */ +public class ConversationalScopeContainer extends AbstractScopeContainer implements ScopeContainer { + private Store nonDurableStore; + private Map components; + + public ConversationalScopeContainer(Store store, WorkContext workContext, final ScopeContainerMonitor monitor) { + super(workContext, monitor); + this.nonDurableStore = store; + if (store != null) { + store.addListener(new ExpirationListener(monitor)); + } + components = new ConcurrentHashMap(); + } + + public Scope getScope() { + return Scope.CONVERSATION; + } + + public void onEvent(Event event) { + checkInit(); + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + lifecycleState = STOPPED; + } + + public void register(AtomicComponent component) { + components.put(component, component); + component.addListener(this); + } + + @Override + public Object getInstance(AtomicComponent component) throws TargetResolutionException { + String conversationId = getConversationId(); + try { + workContext.setCurrentAtomicComponent(component); + Object instance = nonDurableStore.readRecord(component, conversationId); + if (instance != null) { + if (component.getMaxIdleTime() > 0) { + // update expiration + long expire = System.currentTimeMillis() + component.getMaxIdleTime(); + nonDurableStore.updateRecord(component, conversationId, instance, expire); + } + } else { + instance = component.createInstance(); + long expire = calculateExpiration(component); + nonDurableStore.insertRecord(component, conversationId, instance, expire); + component.init(instance); + } + return instance; + } catch (StoreReadException e) { + throw new TargetResolutionException("Error retrieving target instance", e); + } catch (StoreWriteException e) { + throw new TargetResolutionException("Error persisting target instance", e); + } finally { + workContext.setCurrentAtomicComponent(null); + } + } + + public Object getAssociatedInstance(AtomicComponent component) throws TargetResolutionException { + String conversationId = getConversationId(); + try { + workContext.setCurrentAtomicComponent(component); + Object instance = nonDurableStore.readRecord(component, conversationId); + if (instance != null) { + if (component.getMaxIdleTime() > 0) { + // update expiration + long expire = System.currentTimeMillis() + component.getMaxIdleTime(); + nonDurableStore.updateRecord(component, conversationId, instance, expire); + } + return instance; + } else { + throw new TargetNotFoundException(component.getName()); + } + } catch (StoreReadException e) { + throw new TargetResolutionException("Error retrieving target instance", e); + } catch (StoreWriteException e) { + throw new TargetResolutionException("Error persisting target instance", e); + } finally { + workContext.setCurrentAtomicComponent(null); + } + } + + public void persistNew(AtomicComponent component, String id, Object instance, long expiration) + throws PersistenceException { + try { + nonDurableStore.insertRecord(component, id, instance, expiration); + } catch (StoreWriteException e) { + throw new PersistenceException(e); + } + } + + public void persist(AtomicComponent component, String id, Object instance, long expiration) + throws PersistenceException { + try { + nonDurableStore.updateRecord(component, id, instance, expiration); + } catch (StoreWriteException e) { + throw new PersistenceException(e); + } + } + + public void remove(AtomicComponent component) throws PersistenceException { + String conversationId = getConversationId(); + try { + workContext.setCurrentAtomicComponent(component); + Object instance = nonDurableStore.readRecord(component, conversationId); + if (instance != null) { + nonDurableStore.removeRecord(component, conversationId); + } + } catch (StoreReadException e) { + throw new PersistenceException(e); + } catch (StoreWriteException e) { + throw new PersistenceException(e); + } + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) { + throw new UnsupportedOperationException(); + } + + /** + * Returns the conversation id associated with the current invocation context + */ + private String getConversationId() { + String conversationId = (String) workContext.getIdentifier(Scope.CONVERSATION); + assert conversationId != null; + return conversationId; + } + + private long calculateExpiration(AtomicComponent component) { + if (component.getMaxAge() > 0) { + long now = System.currentTimeMillis(); + return now + component.getMaxAge(); + } else if (component.getMaxIdleTime() > 0) { + long now = System.currentTimeMillis(); + return now + component.getMaxIdleTime(); + } else { + return Store.DEFAULT_EXPIRATION_OFFSET; + } + } + + /** + * Receives expiration events from the store and notifies the corresponding atomic component + */ + private static class ExpirationListener implements RuntimeEventListener { + private final ScopeContainerMonitor monitor; + + public ExpirationListener(ScopeContainerMonitor monitor) { + this.monitor = monitor; + } + + public void onEvent(Event event) { + if (event instanceof StoreExpirationEvent) { + StoreExpirationEvent expiration = (StoreExpirationEvent) event; + SCAObject object = expiration.getOwner(); + assert object instanceof AtomicComponent; + AtomicComponent owner = (AtomicComponent) object; + try { + owner.destroy(expiration.getInstance()); + } catch (TargetDestructionException e) { + monitor.destructionError(e); + } + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java new file mode 100644 index 0000000000..32dfaed8d9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ConversationalScopeObjectFactory.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.services.store.Store; + +import org.apache.tuscany.api.annotation.Monitor; + +/** + * Creates a new Session Scope context + * + * @version $$Rev: 450456 $$ $$Date: 2006-09-27 10:28:36 -0400 (Wed, 27 Sep 2006) $$ + */ +@EagerInit +public class ConversationalScopeObjectFactory implements ObjectFactory { + private WorkContext context; + private Store store; + private ScopeContainerMonitor monitor; + + public ConversationalScopeObjectFactory(@Autowire ScopeRegistry registry, + @Autowire WorkContext context, + @Autowire Store store, + @Monitor ScopeContainerMonitor monitor) { + registry.registerFactory(Scope.CONVERSATION, this); + this.context = context; + this.store = store; + this.monitor = monitor; + } + + public ConversationalScopeContainer getInstance() throws ObjectCreationException { + return new ConversationalScopeContainer(store, context, monitor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java new file mode 100644 index 0000000000..83c79b2367 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.component.event.HttpSessionEnd; + +/** + * A scope context which manages atomic component instances keyed on HTTP session + * + * @version $Rev$ $Date$ + */ +public class HttpSessionScopeContainer extends AbstractScopeContainer { + private final Map> contexts; + private final Map> destroyQueues; + + public HttpSessionScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) { + super(workContext, monitor); + contexts = new ConcurrentHashMap>(); + destroyQueues = new ConcurrentHashMap>(); + } + + public Scope getScope() { + return Scope.SESSION; + } + + public void onEvent(Event event) { + checkInit(); + if (event instanceof HttpSessionEnd) { + Object key = ((HttpSessionEnd) event).getId(); + shutdownInstances(key); + workContext.clearIdentifier(key); + } + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + contexts.clear(); + synchronized (destroyQueues) { + destroyQueues.clear(); + } + lifecycleState = STOPPED; + } + + public void register(AtomicComponent component) { + contexts.put(component, new ConcurrentHashMap()); + component.addListener(this); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) + throws TargetResolutionException { + Object key = workContext.getIdentifier(Scope.SESSION); + assert key != null : "HTTP session key not bound in work context"; + return getInstance(component, key, create); + } + + private InstanceWrapper getInstance(AtomicComponent component, Object key, boolean create) + throws TargetResolutionException { + Map wrappers = contexts.get(component); + InstanceWrapper ctx = wrappers.get(key); + if (ctx == null && !create) { + return null; + } + if (ctx == null) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + wrappers.put(key, ctx); + List destroyQueue = destroyQueues.get(key); + if (destroyQueue == null) { + destroyQueue = new ArrayList(); + destroyQueues.put(key, destroyQueue); + } + synchronized (destroyQueue) { + destroyQueue.add(ctx); + } + } + return ctx; + + } + + private void shutdownInstances(Object key) { + List destroyQueue = destroyQueues.remove(key); + if (destroyQueue != null) { + for (Map map : contexts.values()) { + map.remove(key); + } + ListIterator iter = destroyQueue.listIterator(destroyQueue.size()); + synchronized (destroyQueue) { + while (iter.hasPrevious()) { + try { + iter.previous().stop(); + } catch (TargetDestructionException e) { + monitor.destructionError(e); + } + } + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java new file mode 100644 index 0000000000..14713f9144 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.api.annotation.Monitor; + +/** + * Creates a new HTTP session scope context + * + * @version $$Rev$$ $$Date$$ + */ +@EagerInit +public class HttpSessionScopeObjectFactory implements ObjectFactory { + private WorkContext context; + private ScopeContainerMonitor monitor; + + public HttpSessionScopeObjectFactory(@Autowire ScopeRegistry registry, + @Autowire WorkContext context, + @Monitor ScopeContainerMonitor monitor) { + registry.registerFactory(Scope.SESSION, this); + this.context = context; + this.monitor = monitor; + } + + public HttpSessionScopeContainer getInstance() throws ObjectCreationException { + return new HttpSessionScopeContainer(context, monitor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java new file mode 100644 index 0000000000..50f4a31128 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetInitializationException; + +/** + * Provides lifecycle management for an implementation instance associated with an {@link + * org.apache.tuscany.spi.component.AtomicComponent} for use by the atomic component's associated {@link + * org.apache.tuscany.spi.component.ScopeContainer} + * + * @version $Rev$ $Date$ + */ +public interface InstanceWrapper { + + Object getInstance(); + + boolean isStarted(); + + void start() throws TargetInitializationException; + + void stop() throws TargetDestructionException; + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java new file mode 100644 index 0000000000..c4648d1e7b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetInitializationException; + +/** + * Default implementation of an InstanceWrapper + * + * @version $$Rev$$ $$Date$$ + */ +public class InstanceWrapperImpl implements InstanceWrapper { + private Object instance; + private AtomicComponent component; + private boolean started; + + public InstanceWrapperImpl(AtomicComponent component, Object instance) { + assert component != null; + assert instance != null; + this.component = component; + this.instance = instance; + } + + public boolean isStarted() { + return started; + } + + public Object getInstance() { + if (!started) { + throw new IllegalStateException("Instance not started"); + } + return instance; + } + + public void start() throws TargetInitializationException { + component.init(instance); + started = true; + } + + public void stop() throws TargetDestructionException { + component.destroy(instance); + started = false; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java new file mode 100644 index 0000000000..22beaae740 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.component.event.RequestEnd; + +/** + * A scope context which manages atomic component instances keyed on the current request context + * + * @version $Rev$ $Date$ + */ +public class RequestScopeContainer extends AbstractScopeContainer { + private final Map> contexts; + private final Map> destroyQueues; + + public RequestScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) { + super(workContext, monitor); + contexts = new ConcurrentHashMap>(); + destroyQueues = new ConcurrentHashMap>(); + } + + public Scope getScope() { + return Scope.REQUEST; + } + + public void onEvent(Event event) { + checkInit(); + if (event instanceof RequestEnd) { + shutdownInstances(Thread.currentThread()); + } + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + contexts.clear(); + synchronized (destroyQueues) { + destroyQueues.clear(); + } + lifecycleState = STOPPED; + } + + public void register(AtomicComponent component) { + contexts.put(component, new ConcurrentHashMap()); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) + throws TargetResolutionException { + Map instanceContextMap = contexts.get(component); + assert instanceContextMap != null : "Atomic component not registered"; + InstanceWrapper ctx = instanceContextMap.get(Thread.currentThread()); + if (ctx == null && !create) { + return null; + } + if (ctx == null) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + instanceContextMap.put(Thread.currentThread(), ctx); + List destroyQueue = destroyQueues.get(Thread.currentThread()); + if (destroyQueue == null) { + destroyQueue = new ArrayList(); + destroyQueues.put(Thread.currentThread(), destroyQueue); + } + synchronized (destroyQueue) { + destroyQueue.add(ctx); + } + } + return ctx; + } + + private void shutdownInstances(Thread key) { + List destroyQueue = destroyQueues.remove(key); + if (destroyQueue != null && destroyQueue.size() > 0) { + Thread thread = Thread.currentThread(); + for (Map map : contexts.values()) { + map.remove(thread); + } + ListIterator iter = destroyQueue.listIterator(destroyQueue.size()); + synchronized (destroyQueue) { + while (iter.hasPrevious()) { + try { + iter.previous().stop(); + } catch (TargetDestructionException e) { + monitor.destructionError(e); + } + } + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java new file mode 100644 index 0000000000..0377bcd548 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.WorkContext; + +import org.apache.tuscany.api.annotation.Monitor; + +/** + * Creates a new request scope context + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestScopeObjectFactory implements ObjectFactory { + private WorkContext context; + private ScopeContainerMonitor monitor; + + + public RequestScopeObjectFactory(@Autowire WorkContext context, @Monitor ScopeContainerMonitor monitor) { + this.context = context; + this.monitor = monitor; + } + + public RequestScopeContainer getInstance() throws ObjectCreationException { + return new RequestScopeContainer(context, monitor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java new file mode 100644 index 0000000000..da338dd0ef --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.model.Scope; + +/** + * The default implementation of a scope registry + * + * @version $Rev$ $Date$ + */ +public class ScopeRegistryImpl implements ScopeRegistry { + private final Map scopeCache = + new ConcurrentHashMap(); + private final Map> factoryCache = + new ConcurrentHashMap>(); + + public ScopeContainer getScopeContainer(Scope scope) { + assert Scope.COMPOSITE != scope; + ScopeContainer container = scopeCache.get(scope); + if (container == null) { + ObjectFactory factory = factoryCache.get(scope); + if (factory != null) { + container = factory.getInstance(); + container.start(); + scopeCache.put(scope, container); + } + } + return container; + } + + public void registerFactory(Scope scope, ObjectFactory factory) { + factoryCache.put(scope, factory); + } + + public void deregisterFactory(Scope scope) { + factoryCache.remove(scope); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java new file mode 100644 index 0000000000..cbd47b6cdd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +/** + * A scope context which manages stateless atomic component instances in a non-pooled fashion + * + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainer extends AbstractScopeContainer { + + public StatelessScopeContainer(WorkContext workContext, ScopeContainerMonitor monitor) { + super(workContext, monitor); + } + + public Scope getScope() { + return Scope.STATELESS; + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + lifecycleState = STOPPED; + } + + public void onEvent(Event event) { + } + + public void register(AtomicComponent component) { + checkInit(); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component, boolean create) + throws TargetResolutionException { + // there never is a previously associated instance, return null + if (!create) { + return null; + } + InstanceWrapper ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + return ctx; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java new file mode 100644 index 0000000000..8e05510723 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.api.annotation.Monitor; + +/** + * Creates a new stateless scope context + * + * @version $$Rev$$ $$Date$$ + */ +@EagerInit +public class StatelessScopeObjectFactory implements ObjectFactory { + private WorkContext context; + private ScopeContainerMonitor monitor; + + public StatelessScopeObjectFactory(@Autowire ScopeRegistry registry, + @Autowire WorkContext context, + @Monitor ScopeContainerMonitor monitor) { + registry.registerFactory(Scope.STATELESS, this); + this.context = context; + this.monitor = monitor; + } + + public StatelessScopeContainer getInstance() throws ObjectCreationException { + return new StatelessScopeContainer(context, monitor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java new file mode 100644 index 0000000000..aedd715fed --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java @@ -0,0 +1,250 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.ExceptionHandler; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.idl.ServiceFaultException; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.Wire; + +/** + * An interceptor to transform data accross databindings on the wire + * + * @version $Rev$ $Date$ + */ +public class DataBindingInteceptor implements Interceptor { + private Interceptor next; + + private CompositeComponent compositeComponent; + + private Operation sourceOperation; + + private Operation targetOperation; + + private Mediator mediator; + + public DataBindingInteceptor(Wire sourceWire, Operation sourceOperation, Operation targetOperation) { + super(); + // this.sourceWire = sourceWire; + this.sourceOperation = sourceOperation; + // this.targetWire = targetWire; + this.targetOperation = targetOperation; + this.compositeComponent = sourceWire.getContainer().getParent(); + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#getNext() + */ + public Interceptor getNext() { + return next; + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#invoke(org.apache.tuscany.spi.wire.Message) + */ + /* + * (non-Javadoc) + * + * @see org.apache.tuscany.spi.wire.Interceptor#invoke(org.apache.tuscany.spi.wire.Message) + */ + public Message invoke(Message msg) { + Object input = transform(msg.getBody(), sourceOperation.getInputType(), targetOperation.getInputType()); + msg.setBody(input); + Message resultMsg = next.invoke(msg); + Object result = resultMsg.getBody(); + 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 DataType(DataBinding.IDL_OUTPUT, Object.class, targetOperation.getOutputType()); + + targetType.setOperation(targetOperation.getOutputType().getOperation()); + DataType sourceType = + new DataType(DataBinding.IDL_OUTPUT, Object.class, sourceOperation.getOutputType()); + sourceType.setOperation(sourceOperation.getOutputType().getOperation()); + + 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 ServiceFaultException) { + if (((ServiceFaultException)result).isMatchingType(exType.getLogical())) { + targetDataType = exType; + break; + } + + } else { + targetDataType = exType; + break; + } + } + } + + if (targetDataType == null) { + // Not a business exception + return resultMsg; + } + + DataType targetFaultType = getFaultType(targetDataType); + if (targetFaultType == null) { + throw new TransformationException("Target fault type cannot be resolved"); + } + + // 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 && targetFaultType.getLogical().equals(faultType.getLogical())) { + sourceDataType = exType; + sourceFaultType = faultType; + break; + } + } + + if (sourceFaultType == null) { + throw new TransformationException("No matching source fault type is found"); + } + + Object newResult = + transformException(result, targetDataType, sourceDataType, targetFaultType, sourceFaultType); + if (newResult != result) { + resultMsg.setBodyWithFault(newResult); + } + } + + } else { + assert !(result instanceof Throwable) : "Expected messages that are not throwable " + result; + + Object newResult = transform(result, targetType, sourceType); + if (newResult != result) { + resultMsg.setBody(newResult); + } + } + + return resultMsg; + } + + private Object transform(Object source, DataType sourceType, DataType targetType) { + if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) { + return source; + } + Map, Object> metadata = new HashMap, Object>(); + metadata.put(CompositeComponent.class, compositeComponent); + return mediator.mediate(source, sourceType, targetType, metadata); + } + + private DataType getFaultType(DataType exceptionType) { + // FIXME: We cannot assume the exception will have a databinding set + DataBinding targetDataBinding = + mediator.getDataBindingRegistry().getDataBinding(exceptionType.getDataBinding()); + if (targetDataBinding == null) { + return null; + } + ExceptionHandler targetHandler = targetDataBinding.getExceptionHandler(); + if (targetHandler == null) { + return null; + } + return targetHandler.getFaultType(exceptionType); + } + + /** + * @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, Object> metadata = new HashMap, Object>(); + metadata.put(CompositeComponent.class, compositeComponent); + + DataType> eSourceDataType = + new DataType>("idl:fault", sourceExType.getPhysical(), sourceType); + DataType> eTargetDataType = + new DataType>("idl:fault", targetExType.getPhysical(), targetType); + + return mediator.mediate(source, eSourceDataType, eTargetDataType, metadata); + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#isOptimizable() + */ + public boolean isOptimizable() { + return false; + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#setNext(org.apache.tuscany.spi.wire.Interceptor) + */ + public void setNext(Interceptor next) { + this.next = next; + } + + /** + * @param mediator the mediator to set + */ + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java new file mode 100644 index 0000000000..6e176cf0a6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.apache.tuscany.api.annotation.DataType; +import org.apache.tuscany.api.annotation.IDLMapping; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorExtension; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; + +/** + * The databinding annotation processor for java interfaces + * + * @version $Rev$ $Date$ + */ +public class DataBindingJavaInterfaceProcessor extends JavaInterfaceProcessorExtension { + private static final Class[] SIMPLE_JAVA_TYPES = + {Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Date.class, + Calendar.class, GregorianCalendar.class, Duration.class, XMLGregorianCalendar.class, BigInteger.class, + BigDecimal.class}; + + private static final Set SIMPLE_TYPE_SET = new HashSet(Arrays.asList(SIMPLE_JAVA_TYPES)); + + private DataBindingRegistry dataBindingRegistry; + + public DataBindingJavaInterfaceProcessor(@Autowire + DataBindingRegistry dataBindingRegistry) { + super(); + this.dataBindingRegistry = dataBindingRegistry; + } + + public void visitInterface(Class clazz, Class callbackClass, JavaServiceContract contract) + throws InvalidServiceContractException { + if (!contract.isRemotable()) { + return; + } + Map> operations = contract.getOperations(); + processInterface(clazz, contract, operations); + if (callbackClass != null) { + Map> callbackOperations = contract.getCallbackOperations(); + processInterface(callbackClass, contract, callbackOperations); + } + } + + private void processInterface(Class clazz, JavaServiceContract contract, + Map> operations) { + IDLMapping interfaceMapping = clazz.getAnnotation(IDLMapping.class); + DataType interfaceDataType = clazz.getAnnotation(DataType.class); + if (interfaceDataType != null) { + contract.setDataBinding(interfaceDataType.name()); + } + for (Method method : clazz.getMethods()) { + Operation operation = operations.get(method.getName()); + DataType operationDataType = method.getAnnotation(DataType.class); + if (operationDataType == null) { + operationDataType = interfaceDataType; + } + + if (operationDataType != null) { + operation.setDataBinding(operationDataType.name()); + // FIXME: [rfeng] Keep data context as metadata? + } + IDLMapping operationMapping = clazz.getAnnotation(IDLMapping.class); + if (operationMapping == null) { + operationMapping = interfaceMapping; + } + + if (operationMapping != null) { + operation.setDataBinding(operationMapping.dataBinding()); + operation.setWrapperStyle(operationMapping.wrapperStyle()); + } + // String dataBinding = operation.getDataBinding(); + + Annotation[] annotations = null; + if (operationDataType != null) { + annotations = new Annotation[] {operationDataType}; + } + // FIXME: We need a better way to identify simple java types + for (org.apache.tuscany.spi.model.DataType d : operation.getInputType().getLogical()) { + dataBindingRegistry.introspectType(d, annotations); + } + if (operation.getOutputType() != null) { + dataBindingRegistry.introspectType(operation.getOutputType(), annotations); + } + for (org.apache.tuscany.spi.model.DataType d : operation.getFaultTypes()) { + dataBindingRegistry.introspectType(d, annotations); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java new file mode 100644 index 0000000000..8c7f7e28ad --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.lang.annotation.Annotation; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.core.databinding.javabeans.JavaBeansDataBinding; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.EagerInit; + +/** + * The default implementation of a data binding registry + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class DataBindingRegistryImpl implements DataBindingRegistry { + private final Map bindings = new HashMap(); + + public DataBinding getDataBinding(String id) { + if (id == null) { + return null; + } + return bindings.get(id.toLowerCase()); + } + + public void register(DataBinding dataBinding) { + bindings.put(dataBinding.getName().toLowerCase(), dataBinding); + String[] aliases = dataBinding.getAliases(); + if (aliases != null) { + for (String alias : aliases) { + bindings.put(alias.toLowerCase(), dataBinding); + } + } + } + + public DataBinding unregister(String id) { + if (id == null) { + return null; + } + DataBinding dataBinding = bindings.remove(id.toLowerCase()); + if (dataBinding != null) { + String[] aliases = dataBinding.getAliases(); + if (aliases != null) { + for (String alias : aliases) { + bindings.remove(alias.toLowerCase()); + } + } + } + return dataBinding; + } + + private Set getDataBindings() { + return new HashSet(bindings.values()); + } + + public boolean introspectType(DataType dataType, Annotation[] annotations) { + for (DataBinding binding : getDataBindings()) { + // don't introspect for JavaBeansDatabinding as all javatypes will + // anyways match to its basetype + // which is java.lang.Object. Default to this only if no databinding + // results + if (!binding.getName().equals(JavaBeansDataBinding.NAME)) { + if (binding.introspect(dataType, annotations)) { + return true; + } + } + } + // FIXME: Should we honor the databinding from operation/interface + // level? + Object physical = dataType.getPhysical(); + if (physical instanceof Class) { + if (physical == Object.class || Throwable.class.isAssignableFrom((Class)physical)) { + return false; + } + } + dataType.setDataBinding(JavaBeansDataBinding.NAME); + return false; + } + + public DataType introspectType(Object value) { + DataType dataType = null; + for (DataBinding binding : getDataBindings()) { + // don't introspect for JavaBeansDatabinding as all javatypes will + // anyways match to its basetype + // which is java.lang.Object. Default to this only if no databinding + // results + if (!binding.getName().equals(JavaBeansDataBinding.NAME)) { + dataType = binding.introspect(value); + } + if (dataType != null) { + return dataType; + } + } + return new DataType(JavaBeansDataBinding.NAME, value.getClass(), value.getClass()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java new file mode 100644 index 0000000000..e687a161eb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WirePostProcessorExtension; +import org.osoa.sca.annotations.Constructor; + +/** + * This processor is responsible to add an interceptor to invocation chain if the source and target operations have + * different databinding requirements + * + * @version $Rev$ $Date$ + */ +public class DataBindingWirePostProcessor extends WirePostProcessorExtension { + private Mediator mediator; + + @Constructor({"mediator"}) + public DataBindingWirePostProcessor(@Autowire Mediator mediator) { + super(); + this.mediator = mediator; + } + + public void process(OutboundWire source, InboundWire target) { + Map, OutboundInvocationChain> chains = source.getInvocationChains(); + for (Map.Entry, OutboundInvocationChain> entry : chains.entrySet()) { + Operation sourceOperation = entry.getKey(); + Operation targetOperation = + getTargetOperation(target.getInvocationChains().keySet(), sourceOperation.getName()); + String sourceDataBinding = sourceOperation.getDataBinding(); + String targetDataBinding = targetOperation.getDataBinding(); + if (sourceDataBinding == null && targetDataBinding == null) { + continue; + } + if (sourceDataBinding == null || targetDataBinding == null + || !sourceDataBinding.equals(targetDataBinding)) { + // Add the interceptor to the source side because multiple + // references can be wired + // to the same service + DataBindingInteceptor interceptor = + new DataBindingInteceptor(source, sourceOperation, targetOperation); + interceptor.setMediator(mediator); + entry.getValue().addInterceptor(0, interceptor); + } + } + + // Check if there's a callback + Map callbackOperations = source.getServiceContract().getCallbackOperations(); + if (callbackOperations == null || callbackOperations.isEmpty()) { + return; + } + Object targetAddress = source.getContainer().getName(); + Map, OutboundInvocationChain> callbackChains = + target.getSourceCallbackInvocationChains(targetAddress); + if (callbackChains == null) { + // callback chains could be null + return; + } + for (Map.Entry, OutboundInvocationChain> entry : callbackChains.entrySet()) { + Operation sourceOperation = entry.getKey(); + Operation targetOperation = + getTargetOperation(source.getTargetCallbackInvocationChains().keySet(), sourceOperation + .getName()); + String sourceDataBinding = sourceOperation.getDataBinding(); + String targetDataBinding = targetOperation.getDataBinding(); + if (sourceDataBinding == null && targetDataBinding == null) { + continue; + } + if (sourceDataBinding == null || targetDataBinding == null + || !sourceDataBinding.equals(targetDataBinding)) { + // Add the interceptor to the source side because multiple + // references can be wired + // to the same service + DataBindingInteceptor interceptor = + new DataBindingInteceptor(source, sourceOperation, targetOperation); + interceptor.setMediator(mediator); + entry.getValue().addInterceptor(0, interceptor); + } + } + } + + public void process(InboundWire source, OutboundWire target) { + SCAObject container = source.getContainer(); + // Either Service or Reference + boolean isReference = container instanceof ReferenceBinding; + + Map, InboundInvocationChain> chains = source.getInvocationChains(); + for (Map.Entry, InboundInvocationChain> entry : chains.entrySet()) { + Operation sourceOperation = entry.getKey(); + Operation targetOperation = + getTargetOperation(target.getInvocationChains().keySet(), sourceOperation.getName()); + String sourceDataBinding = sourceOperation.getDataBinding(); + String targetDataBinding = targetOperation.getDataBinding(); + if (sourceDataBinding == null && targetDataBinding == null) { + continue; + } + if (sourceDataBinding == null || targetDataBinding == null + || !sourceDataBinding.equals(targetDataBinding)) { + // Add the interceptor to the source side + DataBindingInteceptor interceptor = + new DataBindingInteceptor(source, sourceOperation, targetOperation); + interceptor.setMediator(mediator); + if (isReference) { + // FIXME: We need a better way to position the interceptors + target.getInvocationChains().get(targetOperation).addInterceptor(0, interceptor); + Interceptor tail = entry.getValue().getTailInterceptor(); + if (tail != null) { + // HACK to relink the bridging interceptor + tail.setNext(interceptor); + } + } else { + entry.getValue().addInterceptor(0, interceptor); + } + + } + } + } + + private Operation getTargetOperation(Set> operations, String operationName) { + for (Operation op : operations) { + if (op.getName().equals(operationName)) { + return op; + } + } + return null; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java new file mode 100644 index 0000000000..10731f8c53 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.ModelObject; + +import org.osoa.sca.annotations.Constructor; + +/** + * The StAX loader for data type + */ +public class DataTypeLoader extends LoaderExtension { + public static final QName DATA_BINDING = + new QName("http://tuscany.apache.org/xmlns/sca/databinding/1.0", "databinding"); + + @Constructor({"registry"}) + public DataTypeLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + @Override + public QName getXMLType() { + return DATA_BINDING; + } + + public DataType load(CompositeComponent parent, + ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert DATA_BINDING.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + LoaderUtil.skipToEndElement(reader); + if (name == null) { + throw new InvalidValueException("The 'name' attrbiute is required"); + } + DataType dataType = new DataType(name, Object.class, Object.class); + return dataType; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java new file mode 100755 index 0000000000..02adf5860c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java @@ -0,0 +1,357 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Directed, weighted graph + * + * @param The type of vertex object + * @param The type of edge object + */ +public class DirectedGraph { + private final Map vertices = new HashMap(); + + /** + * Key for the shortest path cache + */ + private final class VertexPair { + private Vertex source; + + private Vertex target; + + /** + * @param source + * @param target + */ + private VertexPair(Vertex source, Vertex target) { + super(); + this.source = source; + this.target = target; + } + + public boolean equals(Object object) { + if (!VertexPair.class.isInstance(object)) { + return false; + } + VertexPair pair = (VertexPair)object; + return source == pair.source && target == pair.target; + } + + public int hashCode() { + int x = source == null ? 0 : source.hashCode(); + int y = target == null ? 0 : target.hashCode(); + return x ^ y; + } + + } + + private final Map paths = 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 Vertex(V value) { + this.value = value; + } + + public String toString() { + return "(" + value + ")"; + } + + public V getValue() { + return value; + } + + public Map getOutEdges() { + return outEdges; + } + + } + + /** + * An Edge connects two vertices in one direction + */ + public final class Edge { + private Vertex sourceVertex; + + private Vertex targetVertex; + + private E value; + + private int weight; + + public Edge(Vertex source, Vertex target, E value, int weight) { + this.sourceVertex = source; + this.targetVertex = target; + this.value = value; + this.weight = weight; + } + + public String toString() { + return sourceVertex + "->" + targetVertex + "[" + value + "," + weight + "]"; + } + + public E getValue() { + return value; + } + + public void setValue(E value) { + this.value = value; + } + + public Vertex getTargetVertex() { + return targetVertex; + } + + public void setTargetVertex(Vertex vertex) { + this.targetVertex = vertex; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public Vertex getSourceVertex() { + return sourceVertex; + } + + public void setSourceVertex(Vertex sourceVertex) { + this.sourceVertex = sourceVertex; + } + } + + private final class Node implements Comparable { + + private long distance = Integer.MAX_VALUE; + + private Node previous; // NOPMD by rfeng on 9/26/06 9:17 PM + + private Vertex vertex; // NOPMD by rfeng on 9/26/06 9:17 PM + + private Node(Vertex vertex) { + this.vertex = vertex; + } + + public int compareTo(Node o) { + return (distance > o.distance) ? 1 : ((distance == o.distance) ? 0 : -1); + } + } + + public void addEdge(V source, V target, E edgeValue, int weight) { + Vertex s = getVertex(source); + if (s == null) { + s = new Vertex(source); + vertices.put(source, s); + } + Vertex t = getVertex(target); + if (t == null) { + t = new Vertex(target); + vertices.put(target, t); + } + Edge edge = new Edge(s, t, edgeValue, weight); + s.outEdges.put(t, edge); + } + + public Vertex getVertex(V source) { + Vertex s = vertices.get(source); + return s; + } + + public boolean removeEdge(V source, V target) { + Vertex s = getVertex(source); + if (s == null) { + return false; + } + + Vertex t = getVertex(target); + if (t == null) { + return false; + } + + return s.outEdges.remove(t) != null; + + } + + public Edge getEdge(Vertex source, Vertex target) { + return source.outEdges.get(target); + } + + public Edge getEdge(V source, V target) { + return getEdge(getVertex(source), getVertex(target)); + } + + /** + * Get the shortes path from the source vertex to the target vertex using + * Dijkstra's algorithm. If there's no path, null will be returned. If the + * source is the same as the target, it returns a path with empty edges with + * weight 0. + * + * @param sourceValue The value identifies the source + * @param targetValue The value identifies the target + * @return The shortest path + */ + public Path getShortestPath(V sourceValue, V targetValue) { + Vertex source = getVertex(sourceValue); + if (source == null) { + return null; + } + Vertex target = getVertex(targetValue); + if (target == null) { + return null; + } + + VertexPair pair = new VertexPair(source, target); + if (paths.containsKey(pair)) { + return paths.get(pair); + } + + // HACK: To support same vertex + if (source == target) { + Path path = new Path(); + Edge edge = getEdge(source, target); + if (edge != null) { + path.addEdge(edge); + } + paths.put(pair, path); + return path; + } + + Map nodes = new HashMap(); + for (Vertex v : vertices.values()) { + Node node = new Node(v); + if (v == source) { + node.distance = 0; + } + nodes.put(v, node); + } + + Set otherNodes = new HashSet(nodes.values()); + Set nodesOnPath = new HashSet(); + while (!otherNodes.isEmpty()) { + Node nextNode = extractMin(otherNodes); + if (nextNode.vertex == target) { + Path path = getPath(nextNode); + paths.put(pair, path); // Cache it + return path; + } + nodesOnPath.add(nextNode); + for (Edge edge : nextNode.vertex.outEdges.values()) { + Node adjacentNode = nodes.get(edge.targetVertex); + if (nextNode.distance + edge.weight < adjacentNode.distance) { + adjacentNode.distance = nextNode.distance + edge.weight; + adjacentNode.previous = nextNode; + } + } + } + paths.put(pair, null); // Cache it + return null; + } + + /** + * Searches for the vertex u in the vertex set Q that has the least d[u] + * value. That vertex is removed from the set Q and returned to the user. + * + * @param nodes + * @return + */ + private Node extractMin(Set nodes) { + Node node = Collections.min(nodes); + nodes.remove(node); + return node; + } + + /** + * The path between two vertices + */ + public final class Path { + private List edges = new LinkedList(); + + private int weight; + + public int getWeight() { + return weight; + } + + public List getEdges() { + return edges; + } + + public void addEdge(Edge edge) { + edges.add(0, edge); + weight += edge.weight; + } + + public String toString() { + return edges + ", " + weight; + } + } + + private Path getPath(Node t) { + if (t.distance == Integer.MAX_VALUE) { + return null; + } + Path path = new Path(); + Node u = t; + while (u.previous != null) { + Edge edge = getEdge(u.previous.vertex, u.vertex); + path.addEdge(edge); + u = u.previous; + } + return path; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Vertex v : vertices.values()) { + sb.append(v.outEdges.values()).append("\n"); + } + return sb.toString(); + } + + public Map getVertices() { + return vertices; + } + + public void addGraph(DirectedGraph otherGraph) { + for (Vertex v : otherGraph.vertices.values()) { + for (Edge e : v.outEdges.values()) { + addEdge(e.sourceVertex.value, e.targetVertex.value, e.value, e.weight); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Exception2ExceptionTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Exception2ExceptionTransformer.java new file mode 100644 index 0000000000..d1ef0cbd1a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Exception2ExceptionTransformer.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.ExceptionHandler; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.Service; + +/** + * This is a special transformer to transform the exception from one IDL to the + * other one + */ +@Service(Transformer.class) +public class Exception2ExceptionTransformer extends TransformerExtension implements + PullTransformer { + + protected Mediator mediator; + + 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 + */ + @Autowire + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType() + */ + @Override + protected Class getSourceType() { + return Exception.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType() + */ + @Override + protected Class getTargetType() { + return Exception.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.Transformer#getWeight() + */ + public int getWeight() { + return 10000; + } + + @SuppressWarnings("unchecked") + public Exception transform(Exception source, TransformationContext context) { + DataType sourceType = context.getSourceDataType(); + + DataType targetType = context.getTargetDataType(); + + ExceptionHandler exceptionHandler = getExceptionHandler(sourceType); + if (exceptionHandler == null) { + return source; + } + + Object sourceFaultInfo = exceptionHandler.getFaultInfo(source); + Object targetFaultInfo = + mediator.mediate(sourceFaultInfo, sourceType.getLogical(), targetType.getLogical(), context.getMetadata()); + + ExceptionHandler targetHandler = getExceptionHandler(targetType); + + if (targetHandler != null) { + Exception targetException = + targetHandler.createException(targetType, source.getMessage(), targetFaultInfo, source.getCause()); + return targetException; + } + + // FIXME + return source; + + } + + private ExceptionHandler getExceptionHandler(DataType targetType) { + DataType targetFaultType = (DataType)targetType.getLogical(); + DataBinding targetDataBinding = + mediator.getDataBindingRegistry().getDataBinding(targetFaultType.getDataBinding()); + if (targetDataBinding == null) { + return null; + } + ExceptionHandler targetHandler = targetDataBinding.getExceptionHandler(); + return targetHandler; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Group2GroupTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Group2GroupTransformer.java new file mode 100644 index 0000000000..c774336f4c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Group2GroupTransformer.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.Service; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + */ +@Service(Transformer.class) +public class Group2GroupTransformer extends TransformerExtension implements + PullTransformer { + + protected Mediator mediator; + + /** + * @param wrapperHandler + */ + public Group2GroupTransformer() { + super(); + } + + /** + * @param mediator the mediator to set + */ + @Autowire + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + @Override + public String getSourceDataBinding() { + return GroupDataBinding.NAME; + } + + @Override + public String getTargetDataBinding() { + return GroupDataBinding.NAME; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.Transformer#getWeight() + */ + public int getWeight() { + return 10; + } + + @SuppressWarnings("unchecked") + public Object transform(Object source, TransformationContext context) { + DataType sourceType = context.getSourceDataType(); + DataType targetType = context.getTargetDataType(); + + return mediator.mediate(source, sourceType.getLogical(), targetType.getLogical(), context.getMetadata()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/GroupDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/GroupDataBinding.java new file mode 100644 index 0000000000..6f56fbc2d5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/GroupDataBinding.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.apache.tuscany.spi.model.DataType; + +/** + * The base class for a special databinding which represents a group of other databindings + * + * @version $Rev$ $Date$ + */ +public abstract class GroupDataBinding extends DataBindingExtension { + public static final String NAME = "databinding:group"; + + /** + * Marker type is a java class or interface representing the data format. + */ + protected Class[] markerTypes; + + public GroupDataBinding(Class[] types) { + super(NAME, null, GroupDataBinding.class); + this.markerTypes = types; + } + + @SuppressWarnings("unchecked") + public boolean introspect(DataType type, Annotation[] annotations) { + if (markerTypes == null) { + return false; + } + Type physical = type.getPhysical(); + if (physical instanceof ParameterizedType) { + physical = ((ParameterizedType)physical).getRawType(); + } + if (!(physical instanceof Class)) { + return false; + } + Class cls = (Class)physical; + for (Class c : markerTypes) { + if (isTypeOf(c, cls)) { + type.setDataBinding(getDataBinding(c)); + type.setLogical(getLogical(cls, annotations)); + return true; + } + } + return false; + } + + /** + * Test if the given type is a subtype of the base type + * @param markerType + * @param type + * @return + */ + protected boolean isTypeOf(Class markerType, Class type) { + return markerType.isAssignableFrom(type); + } + + /** + * Derive the databinding name from a base class + * @param baseType + * @return + */ + protected String getDataBinding(Class baseType) { + return baseType.getName(); + } + + /** + * Get the logical type + * @param type The java type + * @param annotations + * @return + */ + protected abstract Object getLogical(Class type, Annotation[] annotations); + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java new file mode 100644 index 0000000000..3f3f49f0b8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java @@ -0,0 +1,201 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.WrapperInfo; +import org.osoa.sca.annotations.Service; + +/** + * This is a special transformer to transform the input from one IDL to the + * other one + */ +@Service(Transformer.class) +public class Input2InputTransformer extends TransformerExtension implements + PullTransformer { + + 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 + */ + @Autowire + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.spi.databinding.Transformer#getWeight() + */ + public int getWeight() { + return 10000; + } + + @SuppressWarnings("unchecked") + public Object[] transform(Object[] source, TransformationContext context) { + DataType>> sourceType = context.getSourceDataType(); + Operation sourceOp = (Operation)sourceType.getOperation(); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle(); + + WrapperHandler sourceWrapperHandler = null; + if (sourceWrapped) { + sourceWrapperHandler = getWapperHandler(sourceType.getOperation().getDataBinding(), true); + } + + DataType>> targetType = context.getTargetDataType(); + Operation targetOp = (Operation)targetType.getOperation(); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle(); + WrapperHandler targetWrapperHandler = null; + if (targetWrapped) { + targetWrapperHandler = getWapperHandler(targetType.getOperation().getDataBinding(), true); + } + + if ((!sourceWrapped) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + ElementInfo wrapperElement = wrapper.getInputWrapperElement(); + + // If the source can be wrapped, wrapped it first + if (sourceWrapperHandler != null) { + Object sourceWrapper = sourceWrapperHandler.create(wrapperElement, context); + for (int i = 0; i < source.length; i++) { + ElementInfo argElement = wrapper.getInputChildElements().get(i); + sourceWrapperHandler.setChild(sourceWrapper, i, argElement, source[0]); + } + } + Object targetWrapper = targetWrapperHandler.create(wrapperElement, context); + if (source == null) { + return new Object[] {targetWrapper}; + } + List> 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]; + // List childElements = sourceOp.getWrapper().getInputChildElements(); + Object[] target = null; + + targetWrapperHandler = getWapperHandler(targetType.getOperation().getDataBinding(), false); + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement(); + // Object targetWrapper = + // targetWrapperHandler.create(wrapperElement, context); + DataType targetWrapperType = + new DataType(targetType.getOperation().getDataBinding(), Object.class, + new XMLType(wrapperElement)); + Object targetWrapper = + mediator.mediate(sourceWrapper, + sourceType.getLogical().get(0), + targetWrapperType, + context.getMetadata()); + target = targetWrapperHandler.getChildren(targetWrapper).toArray(); + } else { + Object[] sourceChildren = sourceWrapperHandler.getChildren(sourceWrapper).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 getWapperHandler(String dataBindingId, boolean required) { + DataBinding dataBinding = mediator.getDataBindingRegistry().getDataBinding(dataBindingId); + WrapperHandler wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + if (wrapperHandler == null && required) { + throw new TransformationException( + "No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java new file mode 100644 index 0000000000..2b6d871472 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.TransformerRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.Scope; + +/** + * Default Mediator implementation + */ +@Scope("COMPOSITE") +public class MediatorImpl implements Mediator { + + private DataBindingRegistry dataBindingRegistry; + + private TransformerRegistry transformerRegistry; + + @Autowire + public void setTransformerRegistry(TransformerRegistry transformerRegistry) { + this.transformerRegistry = transformerRegistry; + } + + /** + * @param dataBindingRegistry the dataBindingRegistry to set + */ + @Autowire + public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) { + this.dataBindingRegistry = dataBindingRegistry; + } + + /** + * @see org.apache.tuscany.spi.databinding.Mediator#mediate(java.lang.Object, + * org.apache.tuscany.spi.model.DataType, + * org.apache.tuscany.spi.model.DataType, Map) + */ + @SuppressWarnings("unchecked") + public Object mediate(Object source, + DataType sourceDataType, + DataType targetDataType, + Map, Object> metadata) { + if (sourceDataType == null) { + sourceDataType = dataBindingRegistry.introspectType(source); + } + if (sourceDataType == null) { + return source; + } else if (sourceDataType.equals(targetDataType)) { + return source; + } + + List path = getTransformerChain(sourceDataType, targetDataType); + + Object result = source; + int size = path.size(); + int i = 0; + while (i < size) { + Transformer transformer = path.get(i); + TransformationContext context = + createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata); + // the source and target type + if (transformer instanceof PullTransformer) { + // For intermediate node, set data type to null + result = ((PullTransformer)transformer).transform(result, context); + } else if (transformer instanceof PushTransformer) { + DataPipe dataPipe = (i < size - 1) ? (DataPipe)path.get(++i) : null; + ((PushTransformer)transformer).transform(result, dataPipe.getSink(), context); + result = dataPipe.getResult(); + } + i++; + } + + return result; + } + + private TransformationContext createTransformationContext(DataType sourceDataType, + DataType targetDataType, + int size, + int index, + Transformer transformer, + Map, Object> metadata) { + DataType sourceType = + (index == 0) ? sourceDataType : new DataType(transformer.getSourceDataBinding(), + Object.class, null); + DataType targetType = + (index == size - 1) ? targetDataType : new DataType(transformer.getTargetDataBinding(), + Object.class, null); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + TransformationContext context = + new TransformationContextImpl(sourceType, targetType, classLoader, metadata); + return context; + } + + @SuppressWarnings("unchecked") + public void mediate(Object source, + Object target, + DataType sourceDataType, + DataType targetDataType, + Map, Object> metadata) { + if (source == null) { + // Shortcut for null value + return; + } + if (sourceDataType == null) { + sourceDataType = dataBindingRegistry.introspectType(source); + } + if (sourceDataType == null) { + return; + } else if (sourceDataType.equals(targetDataType)) { + return; + } + + List path = getTransformerChain(sourceDataType, targetDataType); + Object result = source; + int size = path.size(); + for (int i = 0; i < size; i++) { + Transformer transformer = path.get(i); + TransformationContext context = + createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata); + + if (transformer instanceof PullTransformer) { + result = ((PullTransformer)transformer).transform(result, context); + } else if (transformer instanceof PushTransformer) { + DataPipe dataPipe = (i < size - 1) ? (DataPipe)path.get(++i) : null; + Object sink = dataPipe != null ? dataPipe.getSink() : target; + ((PushTransformer)transformer).transform(result, sink, context); + result = (dataPipe != null) ? dataPipe.getResult() : null; + } + } + } + + private List getTransformerChain(DataType sourceDataType, DataType targetDataType) { + String sourceId = sourceDataType.getDataBinding(); + String targetId = targetDataType.getDataBinding(); + List path = transformerRegistry.getTransformerChain(sourceId, targetId); + if (path == null) { + TransformationException ex = new TransformationException("No path found for the transformation"); + ex.addContextName("Source: " + sourceId); + ex.addContextName("Target: " + targetId); + throw ex; + } + return path; + } + + /** + * @return the dataBindingRegistry + */ + public DataBindingRegistry getDataBindingRegistry() { + return dataBindingRegistry; + } + + /** + * @return the transformerRegistry + */ + public TransformerRegistry getTransformerRegistry() { + return transformerRegistry; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java new file mode 100644 index 0000000000..ef5798511a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.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.core.databinding.impl; + +import java.util.List; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.WrapperInfo; +import org.osoa.sca.annotations.Service; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + */ +@Service(Transformer.class) +public class Output2OutputTransformer extends TransformerExtension implements + PullTransformer { + + protected Mediator mediator; + + /** + * @param wrapperHandler + */ + public Output2OutputTransformer() { + super(); + } + + /** + * @param mediator the mediator to set + */ + @Autowire + 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.spi.databinding.extension.TransformerExtension#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.Transformer#getWeight() + */ + public int getWeight() { + return 10; + } + + private WrapperHandler getWapperHandler(Operation operation) { + String dataBindingId; + dataBindingId = operation.getDataBinding(); + DataBinding dataBinding = mediator.getDataBindingRegistry().getDataBinding(dataBindingId); + WrapperHandler wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + if (wrapperHandler == null) { + throw new TransformationException( + "No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + + private WrapperHandler getWapperHandler(String dataBindingId) { + DataBinding dataBinding = mediator.getDataBindingRegistry().getDataBinding(dataBindingId); + return dataBinding == null ? null : dataBinding.getWrapperHandler(); + } + + @SuppressWarnings("unchecked") + public Object transform(Object response, TransformationContext context) { + try { + DataType sourceType = context.getSourceDataType(); + Operation sourceOp = (Operation)sourceType.getOperation(); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle(); + WrapperHandler sourceWrapperHandler = null; + if (sourceWrapped) { + sourceWrapperHandler = getWapperHandler(sourceOp); + } + + DataType targetType = context.getTargetDataType(); + Operation targetOp = (Operation)targetType.getOperation(); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle(); + WrapperHandler targetWrapperHandler = null; + if (targetWrapped) { + targetWrapperHandler = getWapperHandler(targetOp); + } + + if ((!sourceWrapped) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + Object targetWrapper = + targetWrapperHandler.create(wrapper.getOutputWrapperElement(), context); + + List childElements = wrapper.getOutputChildElements(); + 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; + } + targetWrapperHandler = getWapperHandler(targetType.getLogical().getDataBinding()); + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement(); + // Object targetWrapper = + // targetWrapperHandler.create(wrapperElement, context); + DataType targetWrapperType = + new DataType(targetType.getLogical().getDataBinding(), Object.class, + new XMLType(wrapperElement)); + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceType.getLogical(), targetWrapperType, context + .getMetadata()); + return targetWrapperHandler.getChildren(targetWrapper).get(0); + } else { + Object child = sourceWrapperHandler.getChildren(sourceWrapper).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/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java new file mode 100644 index 0000000000..c891ff7a61 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueInterceptor.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.IdentityHashMap; +import java.util.Map; + +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; + +/** + * An interceptor to enforce pass-by-value semantics for remotable interfaces + * + * @version $Rev$ $Date$ + */ +public class PassByValueInterceptor implements Interceptor { + private DataBindingRegistry registry; + private DataBinding[] parameterDatabindings; + private DataBinding resultDataBinding; + + private Interceptor next; + + public PassByValueInterceptor(DataBindingRegistry registry) { + this.registry = registry; + } + + public Interceptor getNext() { + return next; + } + + public boolean isOptimizable() { + return false; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public Message invoke(Message msg) { + Object obj = msg.getBody(); + msg.setBody(copy((Object[])obj)); + Message result = getNext().invoke(msg); + + if (!result.isFault()) { + result.setBody(copy(result.getBody(), getResultDataBinding())); + } + return result; + } + + public Object[] copy(Object[] args) { + if (args == null) { + return null; + } + Object[] copiedArgs = new Object[args.length]; + Map map = new IdentityHashMap(); + for (int i = 0; i < args.length; i++) { + if (args[i] == null) { + copiedArgs[i] = null; + } else { + Object copiedArg = map.get(args[i]); + if (copiedArg != null) { + copiedArgs[i] = copiedArg; + } else { + DataBinding dataBinding = + (getParameterDatabindings() != null) ? getParameterDatabindings()[i] : null; + copiedArg = copy(args[i], dataBinding); + map.put(args[i], copiedArg); + copiedArgs[i] = copiedArg; + } + } + } + return copiedArgs; + } + + public Object copy(Object arg, DataBinding argDataBinding) { + if (arg == null) { + return null; + } + Object copiedArg; + if (argDataBinding != null) { + copiedArg = argDataBinding.copy(arg); + } else { + copiedArg = arg; + DataType dataType = registry.introspectType(arg); + if (dataType != null) { + DataBinding binding = registry.getDataBinding(dataType.getDataBinding()); + if (binding != null) { + copiedArg = binding.copy(arg); + } + } + // FIXME: What to do if it's not recognized? + } + return copiedArg; + } + + public DataBinding[] getParameterDatabindings() { + return parameterDatabindings; + } + + public void setParameterDatabindings(DataBinding[] dataBindings) { + this.parameterDatabindings = dataBindings; + } + + public DataBinding getResultDataBinding() { + return resultDataBinding; + } + + public void setResultDataBinding(DataBinding retDataBinding) { + this.resultDataBinding = retDataBinding; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java new file mode 100644 index 0000000000..a95b0ef073 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PassByValueWirePostProcessor.java @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.extension.AtomicComponentExtension; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WirePostProcessorExtension; + +/** + * This processor is responsible for enforcing the pass-by-value semantics + * required of Remotable interfaces. This is done by adding a pass-by-value + * interceptor to the inbound invocation chain of a target if the target + * interface is Remotable. + * + * @version $Rev$ $Date$ + */ +public class PassByValueWirePostProcessor extends WirePostProcessorExtension { + + private DataBindingRegistry dataBindingRegistry; + + public PassByValueWirePostProcessor() { + super(); + } + + /** + * @param dataBindingRegistry the dataBindingRegistry to set + */ + @Autowire + public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) { + this.dataBindingRegistry = dataBindingRegistry; + } + + public void process(OutboundWire source, InboundWire target) { + PassByValueInterceptor interceptor; + Operation targetOperation; + Operation sourceOperation; + DataBinding[] argsDataBindings; + DataBinding resultDataBinding; + + boolean implAllowsPBR = false; + boolean methodAllowsPBR = false; + + // if the source is a service binding or the target is a reference + // binding do no + // add interceptor since the bindings will ensure passbyvalue semantics + if (!(source.getContainer() instanceof ServiceBinding || target.getContainer() instanceof ReferenceBinding)) { + + if (target.getContainer() instanceof AtomicComponentExtension) { + implAllowsPBR = ((AtomicComponentExtension)target.getContainer()).isAllowsPassByReference(); + } + + Map, InboundInvocationChain> chains = target.getInvocationChains(); + for (Map.Entry, InboundInvocationChain> entry : chains.entrySet()) { + targetOperation = entry.getKey(); + methodAllowsPBR = false; + + if (target.getContainer() instanceof AtomicComponentExtension) { + methodAllowsPBR = + ((AtomicComponentExtension)target.getContainer()).getPassByReferenceMethods() + .contains(targetOperation.getName()); + } + + if (target.getServiceContract().isRemotable() && (!implAllowsPBR && !methodAllowsPBR)) { + sourceOperation = + getSourceOperation(source.getInvocationChains().keySet(), targetOperation.getName()); + + if (null != sourceOperation) { + argsDataBindings = getParameterDataBindings(sourceOperation); + resultDataBinding = getResultDataBinding(sourceOperation); + interceptor = new PassByValueInterceptor(dataBindingRegistry); + interceptor.setParameterDatabindings(argsDataBindings); + interceptor.setResultDataBinding(resultDataBinding); + source.getInvocationChains().get(sourceOperation).addInterceptor(0, interceptor); + /* + * tailInterceptor = + * source.getInvocationChains().get(sourceOperation).getTailInterceptor(); + * if (tailInterceptor != null) { + * tailInterceptor.setNext(passByValueInterceptor); } + */ + } + } + } + + // Check if there's a callback + Map callbackOperations = source.getServiceContract().getCallbackOperations(); + implAllowsPBR = false; + + if (callbackOperations != null && !callbackOperations.isEmpty()) { + if (source.getContainer() instanceof AtomicComponentExtension) { + implAllowsPBR = ((AtomicComponentExtension)source.getContainer()).isAllowsPassByReference(); + } + + Object targetAddress = source.getContainer().getName(); + Map, InboundInvocationChain> callbackChains = source.getTargetCallbackInvocationChains(); + for (Map.Entry, InboundInvocationChain> entry : callbackChains.entrySet()) { + targetOperation = entry.getKey(); + methodAllowsPBR = false; + + if (source.getContainer() instanceof AtomicComponentExtension) { + methodAllowsPBR = + ((AtomicComponentExtension)source.getContainer()).getPassByReferenceMethods() + .contains(targetOperation.getName()); + } + + if (source.getServiceContract().isRemotable() && (!implAllowsPBR && !methodAllowsPBR)) { + sourceOperation = + getSourceOperation(target.getSourceCallbackInvocationChains(targetAddress).keySet(), + targetOperation.getName()); + + argsDataBindings = getParameterDataBindings(targetOperation); + resultDataBinding = getResultDataBinding(targetOperation); + + interceptor = new PassByValueInterceptor(dataBindingRegistry); + interceptor.setParameterDatabindings(argsDataBindings); + interceptor.setResultDataBinding(resultDataBinding); + + entry.getValue().addInterceptor(0, interceptor); + /* + * tailInterceptor = + * target.getSourceCallbackInvocationChains(targetAddress).get(sourceOperation) + * .getTailInterceptor(); if (tailInterceptor != null) { + * tailInterceptor.setNext(passByValueInterceptor); } + */ + } + } + } + } + } + + public void process(InboundWire source, OutboundWire target) { + // to be done if required.. + } + + private Operation getSourceOperation(Set> operations, String operationName) { + for (Operation op : operations) { + if (op.getName().equals(operationName)) { + return op; + } + } + return null; + } + + @SuppressWarnings("unchecked") + private DataBinding[] getParameterDataBindings(Operation operation) { + List> argumentTypes = (List>)operation.getInputType().getLogical(); + DataBinding[] argDataBindings = new DataBinding[argumentTypes.size()]; + int count = 0; + for (DataType argType : argumentTypes) { + argDataBindings[count++] = dataBindingRegistry.getDataBinding(argType.getDataBinding()); + } + return argDataBindings; + } + + private DataBinding getResultDataBinding(Operation operation) { + DataType resultType = (DataType)operation.getOutputType(); + return dataBindingRegistry.getDataBinding(resultType.getDataBinding()); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java new file mode 100755 index 0000000000..388ea710a7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; + +/** + * A utility class to connect PushTransformer and DataPipe to create a + * PullTransformer + * + * @param Source type + * @param Intermidate type + * @param Result type + */ +public class PipedTransformer implements PullTransformer { + private PushTransformer pusher; + + private DataPipe pipe; + + /** + * @param pumper + * @param pipe + */ + public PipedTransformer(PushTransformer pumper, DataPipe pipe) { + super(); + this.pusher = pumper; + this.pipe = pipe; + } + + public R transform(S source, TransformationContext context) { + pusher.transform(source, pipe.getSink(), context); + return pipe.getResult(); + } + + public String getSourceDataBinding() { + return pusher.getSourceDataBinding(); + } + + public String getTargetDataBinding() { + return pipe.getTargetDataBinding(); + } + + public int getWeight() { + return pusher.getWeight() + pipe.getWeight(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java new file mode 100644 index 0000000000..b1550c9f0a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.apache.tuscany.spi.loader.MissingResourceException; + +/** + * Simple databinding represented by a base java type. A SCDL property className is used to customize this component. + *

+ * The following illustrates how a simple data binding can be registered as a SCA component. + *

+ *

+ * <component name="databinding.MyDataBinding">
+ *   <system:implementation.java + * class="org.apache.tuscany.databinding.impl.SimpleDataBinding"/>
+ *   <property name="className">my.Type</property>
+ * </component> + *
+ * + * @version $Rv$ $Date$ + */ +public class SimpleDataBinding extends DataBindingExtension { + + public SimpleDataBinding(@Property(name = "className")String className) throws MissingResourceException { + super(resolve(className)); + } + + private static Class resolve(String className) throws MissingResourceException { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + return Class.forName(className, false, classLoader); + } catch (ClassNotFoundException e) { + classLoader = SimpleDataBinding.class.getClassLoader(); + try { + return Class.forName(className, false, classLoader); + } catch (ClassNotFoundException e1) { + throw new MissingResourceException(className, e1); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java new file mode 100755 index 0000000000..47f340097b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.model.DataType; + +public class TransformationContextImpl implements TransformationContext { + private DataType sourceDataType; + + private DataType targetDataType; + + private final Map, Object> metadata = new HashMap, Object>(); + + private WeakReference classLoaderRef; + + public TransformationContextImpl() { + super(); + setClassLoader(Thread.currentThread().getContextClassLoader()); + } + + public TransformationContextImpl(DataType sourceDataType, + DataType targetDataType, + ClassLoader classLoader, + Map, Object> metadata) { + super(); + this.sourceDataType = sourceDataType; + this.targetDataType = targetDataType; + setClassLoader(classLoader); + if (metadata != null) { + this.metadata.putAll(metadata); + } + } + + public DataType getSourceDataType() { + return sourceDataType; + } + + public DataType getTargetDataType() { + return targetDataType; + } + + public void setSourceDataType(DataType sourceDataType) { + this.sourceDataType = sourceDataType; + } + + public void setTargetDataType(DataType targetDataType) { + this.targetDataType = targetDataType; + } + + public final void setClassLoader(ClassLoader classLoader) { + this.classLoaderRef = new WeakReference(classLoader); + } + + public ClassLoader getClassLoader() { + return classLoaderRef.get(); + } + + public Map, Object> getMetadata() { + return metadata; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java new file mode 100755 index 0000000000..6f5c6d0e73 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.TransformerRegistry; + +/** + * @version $Rev$ $Date$ + */ +@EagerInit +public class TransformerRegistryImpl implements TransformerRegistry { + private DataBindingRegistry dataBindingRegistry; + + private final DirectedGraph graph = new DirectedGraph(); + + public void registerTransformer(String sourceType, String resultType, int weight, Transformer transformer) { + graph.addEdge(sourceType, resultType, transformer, weight); + } + + public void registerTransformer(Transformer transformer) { + graph.addEdge(transformer.getSourceDataBinding(), + transformer.getTargetDataBinding(), + transformer, + transformer.getWeight()); + } + + public boolean unregisterTransformer(String sourceType, String resultType) { + return graph.removeEdge(sourceType, resultType); + } + + public Transformer getTransformer(String sourceType, String resultType) { + DirectedGraph.Edge edge = graph.getEdge(sourceType, resultType); + return (edge == null) ? null : edge.getValue(); + } + + public List getTransformerChain(String sourceType, String resultType) { + String source = normalize(sourceType); + String result = normalize(resultType); + List transformers = new ArrayList(); + DirectedGraph.Path path = graph.getShortestPath(source, result); + if (path == null) { + return null; + } + for (DirectedGraph.Edge edge : path.getEdges()) { + transformers.add(edge.getValue()); + } + return transformers; + } + + public String toString() { + return graph.toString(); + } + + /** + * @param dataBindingRegistry the dataBindingRegistry to set + */ + @Autowire + public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) { + this.dataBindingRegistry = dataBindingRegistry; + } + + /** + * Normalize the id to a name of a data binding as databindings may have aliases + * @param id + * @return + */ + private String normalize(String id) { + if (dataBindingRegistry != null) { + DataBinding dataBinding = dataBindingRegistry.getDataBinding(id); + return dataBinding == null ? id : dataBinding.getName(); + } else { + return id; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java new file mode 100644 index 0000000000..80f9fa04da --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/DOMNode2JavaBeanTransformer.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.javabeans; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.databinding.Transformer; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Transformer to convert data from DOM Node to JavaBean + */ +@Service(Transformer.class) +public class DOMNode2JavaBeanTransformer extends XML2JavaBeanTransformer { + + @Override + public Node getRootElement(Node element) throws XML2JavaMapperException { + if (element instanceof Document) { + return ((Document)element).getDocumentElement(); + } else { + return element; + } + + } + + @Override + public List getChildElements(Node parent) throws XML2JavaMapperException { + NodeList nodeList = parent.getChildNodes(); + List nodeArrayList = new ArrayList(nodeList.getLength()); + for (int count = 0; count < nodeList.getLength(); ++count) { + nodeArrayList.add(nodeList.item(count)); + } + + return nodeArrayList; + } + + @Override + public String getElementName(Node element) throws XML2JavaMapperException { + return element.getLocalName(); + } + + @Override + public String getText(Node element) throws XML2JavaMapperException { + if (element instanceof Document) { + element = ((Document)element).getDocumentElement(); + } + return element.getTextContent(); + } + + @Override + public boolean isTextElement(Node element) throws XML2JavaMapperException { + return element.getNodeType() == Node.TEXT_NODE; + } + + public Class getSourceType() { + return Node.class; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java new file mode 100644 index 0000000000..3f88a4ee89 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/Java2XMLMapperException.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.javabeans; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * This exception is used to encapsulate and rethrow exceptions that arise out + * of converting JavaBean objects to XML + */ +public class Java2XMLMapperException extends TuscanyRuntimeException { + private static final long serialVersionUID = 6811924384399578686L; + + private QName xmlElementName; + private String javaFieldName; + private Class javaType; + + public Java2XMLMapperException(String message) { + super(message); + } + + public Java2XMLMapperException(Throwable cause) { + super(cause); + } + + public String getJavaFieldName() { + return javaFieldName; + } + + public void setJavaFieldName(String javaFieldName) { + this.javaFieldName = javaFieldName; + } + + public Class getJavaType() { + return javaType; + } + + public void setJavaType(Class javaType) { + this.javaType = javaType; + } + + public QName getXmlElementName() { + return xmlElementName; + } + + public void setXmlElementName(QName xmlElementName) { + this.xmlElementName = xmlElementName; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java new file mode 100644 index 0000000000..5925e87b69 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2DOMNodeTransformer.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.javabeans; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from a JavaBean object to DOM Node + */ +@Service(Transformer.class) +public class JavaBean2DOMNodeTransformer extends JavaBean2XMLTransformer { + + public static final String COLON = ":"; + private Document factory; + + public JavaBean2DOMNodeTransformer() { + super(); + try { + factory = DOMHelper.newDocument(); + } catch (ParserConfigurationException e) { + throw new Java2XMLMapperException(e); + } + } + + @Override + public void appendChild(Node parentElement, Node childElement) throws Java2XMLMapperException { + parentElement.appendChild(childElement); + } + + @Override + public Node createElement(QName qName) throws Java2XMLMapperException { + String qualifedName = + (qName.getPrefix() == null || qName.getPrefix().length() <= 0) ? qName.getLocalPart() + : qName.getPrefix() + COLON + qName.getLocalPart(); + return factory.createElementNS(qName.getNamespaceURI(), qualifedName); + } + + @Override + public Node createText(String textData) throws Java2XMLMapperException { + return factory.createTextNode(textData); + } + + public Class getTargetType() { + return Node.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLStreamReader.java new file mode 100644 index 0000000000..770c8e7254 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLStreamReader.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.javabeans; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.databinding.xml.BeanUtil; +import org.apache.tuscany.core.databinding.xml.XMLDocumentStreamReader; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class JavaBean2XMLStreamReader extends TransformerExtension implements + PullTransformer { + + public XMLStreamReader transform(Object source, TransformationContext context) { + try { + return new XMLDocumentStreamReader(BeanUtil.getXMLStreamReader(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Object.class; + } + + public Class getTargetType() { + return XMLStreamReader.class; + } + + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java new file mode 100644 index 0000000000..c0199eee95 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBean2XMLTransformer.java @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.javabeans; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +/** + * Transformer to convert data from a JavaBean object to xml + */ +@Service(Transformer.class) +public abstract class JavaBean2XMLTransformer extends TransformerExtension implements + PullTransformer { + + public static final String GET = "get"; + public static final String PREFIX = "n"; + public static final String PERIOD = "."; + public static final String FWD_SLASH = "/"; + public static final String HTTP = "http://"; + private static int prefixCount = 1; + + protected SimpleTypeMapperExtension mapper; + + public JavaBean2XMLTransformer() { + this.mapper = new SimpleTypeMapperExtension(); + } + + public T transform(Object source, TransformationContext context) { + QName rootElementName = (QName)context.getTargetDataType().getMetadata("RootElementName"); + if (rootElementName == null) { + rootElementName = new QName(resolveRootElementName(source.getClass())); + } + T root = createElement(rootElementName); + appendChildElements(root, + resolveElementName(source.getClass()), + source.getClass(), + source, + context); + return root; + } + + private void appendChildElements(T parent, + QName elementName, + Class javaType, + Object javaObject, + TransformationContext context) { + T element = null; + if (javaObject != null) { + if (javaType.isPrimitive() || isSimpleJavaType(javaObject)) { + appendChild(parent, createText(mapper.toXMLLiteral(null, javaObject, context))); + } else if (javaType.isArray()) { + boolean arrayDone = false; + Object arrayObject = null; + for (int count = 0; !arrayDone; ++count) { + try { + arrayObject = Array.get(javaObject, count); + element = createElement(elementName); + appendChild(parent, element); + appendChildElements(element, + elementName, + javaType.getComponentType(), + arrayObject, + context); + } catch (ArrayIndexOutOfBoundsException e1) { + arrayDone = true; + } + } + } else { + Field[] javaFields = javaType.getFields(); + for (Field aField : javaFields) { + try { + QName fieldElementName = new QName(aField.getName()); + if (!aField.getType().isArray()) { + element = createElement(fieldElementName); + appendChild(parent, element); + appendChildElements(element, + fieldElementName, + aField.getType(), + aField.get(javaObject), + context); + } else { + appendChildElements(parent, + fieldElementName, + aField.getType(), + aField.get(javaObject), + context); + } + } catch (IllegalAccessException e) { + Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e); + java2xmlEx.setJavaFieldName(aField.getName()); + java2xmlEx.setJavaType(javaType); + throw java2xmlEx; + } + } + + Method[] methods = javaType.getDeclaredMethods(); + String fieldName = null; + for (Method aMethod : methods) { + try { + if (Modifier.isPublic(aMethod.getModifiers()) && aMethod.getName().startsWith(GET) + && aMethod.getParameterTypes().length == 0) { + fieldName = resolveFieldFromMethod(aMethod.getName()); + try { + javaType.getField(fieldName); + } catch (NoSuchFieldException e) { + QName fieldElementName = new QName(fieldName); + if (aMethod.getReturnType().isArray()) { + appendChildElements(parent, fieldElementName, aMethod.getReturnType(), aMethod + .invoke(javaObject, new Object[0]), context); + } else { + element = createElement(fieldElementName); + appendChild(parent, element); + appendChildElements(element, fieldElementName, aMethod.getReturnType(), aMethod + .invoke(javaObject, new Object[0]), context); + } + } + } + } catch (IllegalAccessException e) { + Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e); + java2xmlEx.setJavaFieldName(fieldName); + java2xmlEx.setJavaType(javaType); + throw java2xmlEx; + } catch (InvocationTargetException e) { + Java2XMLMapperException java2xmlEx = new Java2XMLMapperException(e); + java2xmlEx.setJavaFieldName(fieldName); + java2xmlEx.setJavaType(javaType); + throw java2xmlEx; + } + } + } + } + } + + public Class getSourceType() { + return Object.class; + } + + private boolean isSimpleJavaType(Object javaObject) { + if (javaObject instanceof String) { + return true; + } + if (javaObject instanceof Byte || javaObject instanceof Character + || javaObject instanceof Short + || javaObject instanceof Integer + || javaObject instanceof Long + || javaObject instanceof Float + || javaObject instanceof Double) { + return true; + } + if (javaObject instanceof GregorianCalendar || javaObject instanceof Date + || javaObject instanceof XMLGregorianCalendar + || javaObject instanceof byte[] + || javaObject instanceof QName) { + return true; + } + return false; + } + + private String resolveRootElementName(Class javaType) { + if (javaType.isArray()) { + return javaType.getComponentType().getSimpleName() + "_collection"; + } else { + return javaType.getSimpleName() + "_instance"; + } + } + + + private QName resolveElementName(Class javaType) { + if (javaType.isArray()) { + return new QName(javaType.getComponentType().getSimpleName()); + } else { + return new QName(javaType.getSimpleName()); + } + } + + private String resolveFieldFromMethod(String methodName) { + StringBuffer fieldName = new StringBuffer(); + fieldName.append(Character.toLowerCase(methodName.charAt(GET.length()))); + fieldName.append(methodName.substring(GET.length() + 1)); + return fieldName.toString(); + } + + public String getNexPrefix() { + return PREFIX + prefixCount++; + } + + @Override + public int getWeight() { + return JavaBeansDataBinding.HEAVY_WEIGHT; + } + + public abstract T createElement(QName qName) throws Java2XMLMapperException; + public abstract T createText(String textData) throws Java2XMLMapperException; + public abstract void appendChild(T parentElement, T childElement) throws Java2XMLMapperException; +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java new file mode 100644 index 0000000000..58c3728202 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/JavaBeansDataBinding.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.javabeans; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.OutputStream; +import java.io.Serializable; + +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.osoa.sca.annotations.Service; + +/** + * DataBinding for JavaBeans + */ +@Service(DataBinding.class) +public class JavaBeansDataBinding extends DataBindingExtension { + /** + * Defining a weight to a very high number so that the transformer won't be picked + * up by other paths unless it's the only available path + */ + public static final int HEAVY_WEIGHT = 10000; + public static final String NAME = Object.class.getName(); + + public JavaBeansDataBinding() { + super(NAME, Object.class); + } + + public Object copy(Object arg) { + if (arg == null) { + return null; + } + final Class clazz = arg.getClass(); + if (String.class == clazz || clazz.isPrimitive() + || Number.class.isAssignableFrom(clazz) + || Boolean.class.isAssignableFrom(clazz) + || Character.class.isAssignableFrom(clazz) + || Byte.class.isAssignableFrom(clazz)) { + // Immutable classes + return arg; + } + try { + if (arg instanceof Serializable) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = getObjectOutputStream(bos); + oos.writeObject(arg); + oos.close(); + bos.close(); + + ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); + ObjectInputStream ois = getObjectInputStream(bis, clazz.getClassLoader()); + Object objectCopy = ois.readObject(); + ois.close(); + bis.close(); + return objectCopy; + } else { + // return arg; + throw new IllegalArgumentException("Pass-by-value is not supported for the given object"); + } + } catch (Exception e) { + throw new IllegalArgumentException("Pass-by-value is not supported for the given object", e); + } + } + + protected ObjectOutputStream getObjectOutputStream(OutputStream os) throws IOException { + return new ObjectOutputStream(os); + } + + protected ObjectInputStream getObjectInputStream(InputStream is, final ClassLoader cl) throws IOException { + ObjectInputStream ois = new ObjectInputStream(is) { + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + try { + return Class.forName(desc.getName(), false, cl); + } catch (ClassNotFoundException e) { + return super.resolveClass(desc); + } + } + + }; + return ois; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java new file mode 100644 index 0000000000..2013502851 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaBeanTransformer.java @@ -0,0 +1,300 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.javabeans; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.idl.XMLType; +import org.osoa.sca.annotations.Service; + +/** + * Transformer to convert data from XML to JavaBean + */ +@Service(Transformer.class) +public abstract class XML2JavaBeanTransformer extends TransformerExtension implements + PullTransformer { + + public static final String SET = "set"; + + protected SimpleTypeMapperExtension mapper; + + public XML2JavaBeanTransformer() { + this.mapper = new SimpleTypeMapperExtension(); + } + + @Override + public int getWeight() { + return JavaBeansDataBinding.HEAVY_WEIGHT; + } + + public Object transform(T source, TransformationContext context) { + XMLType xmlType = (XMLType) context.getSourceDataType().getLogical(); + return toJavaObject(xmlType.getTypeName(), getRootElement(source), context); + } + + public Object toJavaObject(QName xmlType, T xmlElement, TransformationContext context) { + if (SimpleTypeMapperExtension.isSimpleXSDType(xmlType)) { + return mapper.toJavaObject(xmlType, getText(xmlElement), context); + } else { + Class javaType = (Class)context.getTargetDataType().getPhysical(); + return createJavaObject(xmlElement, javaType, context); + } + } + + @SuppressWarnings("unchecked") + private L createJavaObject(T element, Class javaType, TransformationContext context) + throws XML2JavaMapperException { + List childElements = getChildElements(element); + if (childElements.size() == 1 && isTextElement(childElements.get(0))) { + return (L) mapper.toJavaObject(mapper.getXMLType(javaType).getQName(), + getText(childElements.get(0)), + context); + } else { + String fieldName = null; + try { + L javaInstance = javaType.newInstance(); + Map> arrayFields = new Hashtable>(); + Map> arraySetters = new Hashtable>(); + for (int count = 0; count < childElements.size(); ++count) { + if (!isTextElement(childElements.get(count))) { + fieldName = getElementName(childElements.get(count)); + try { + Field javaField = javaType.getField(fieldName); + setFieldValue(javaInstance, + javaField, + childElements.get(count), + arrayFields, + context); + + } catch (NoSuchFieldException e1) { + setFieldValueUsingSetter(javaType, + javaInstance, + fieldName, + childElements.get(count), + arraySetters, + context); + } + } + } + + setArrayValues(javaInstance, arrayFields, arraySetters); + return javaInstance; + } catch (Exception e2) { + XML2JavaMapperException xml2JavaEx = new XML2JavaMapperException(e2); + xml2JavaEx.setJavaType(javaType); + xml2JavaEx.setJavaFieldName(fieldName); + throw xml2JavaEx; + } + } + } + + private void setFieldValue(Object javaInstance, + Field javaField, + T fieldValue, + Map> arrayFields, + TransformationContext context) throws IllegalAccessException { + Class javaFieldType = (Class) javaField.getType(); + + if (javaFieldType.isArray()) { + Class componentType = javaFieldType.getComponentType(); + List fldValueArray = arrayFields.get(javaField); + if (fldValueArray == null) { + fldValueArray = new ArrayList(); + arrayFields.put(javaField, fldValueArray); + } + fldValueArray.add(createJavaObject(fieldValue, componentType, context)); + } else { + javaField.setAccessible(true); + javaField.set(javaInstance, createJavaObject(fieldValue, javaFieldType, context)); + } + } + + private void setFieldValueUsingSetter(Class javaType, + Object javaInstance, + String fieldName, + T fieldValue, + Map> arraySetters, + TransformationContext context) throws IllegalAccessException, + InvocationTargetException { + char firstChar = Character.toUpperCase(fieldName.charAt(0)); + StringBuilder methodName = new StringBuilder(SET + fieldName); + methodName.setCharAt(SET.length(), firstChar); + boolean methodNotFound = true; + + for (int methodCount = 0; methodNotFound && methodCount < javaType.getMethods().length; ++methodCount) { + Method aMethod = javaType.getMethods()[methodCount]; + if (aMethod.getName().equals(methodName.toString()) + && aMethod.getParameterTypes().length == 1) { + Class paramType = aMethod.getParameterTypes()[0]; + + if (paramType.isArray()) { + Class componentType = paramType.getComponentType(); + List setterValueArray = arraySetters.get(aMethod); + if (setterValueArray == null) { + setterValueArray = new ArrayList(); + arraySetters.put(aMethod, setterValueArray); + } + setterValueArray.add(createJavaObject(fieldValue, componentType, context)); + } else { + aMethod.invoke(javaInstance, new Object[] {createJavaObject(fieldValue, + paramType, + context)}); + } + methodNotFound = false; + } + } + + if (methodNotFound) { + XML2JavaMapperException xml2JavaEx = + new XML2JavaMapperException("No field or setter method to configure xml data"); + xml2JavaEx.setJavaFieldName(fieldName); + xml2JavaEx.setJavaType(javaType); + throw xml2JavaEx; + } + } + + private void setArrayValues(Object javaInstance, + Map> arrayFields, + Map> arraySetters) throws IllegalAccessException, + InvocationTargetException { + if (arrayFields.size() > 0) { + for (Field javaField : arrayFields.keySet()) { + javaField.setAccessible(true); + + if (javaField.getType().getComponentType().isPrimitive()) { + javaField.set(javaInstance, createPrimitiveArray(javaField.getType() + .getComponentType(), + arrayFields.get(javaField))); + } else { + javaField.set(javaInstance, + createNonPrimitiveArray(javaField.getType().getComponentType(), + arrayFields.get(javaField))); + } + } + } + + if (arraySetters.size() > 0) { + for (Method aMethod : arraySetters.keySet()) { + Class paramType = aMethod.getParameterTypes()[0]; + if (paramType.getComponentType().isPrimitive()) { + aMethod.invoke(javaInstance, + new Object[] {createPrimitiveArray(paramType.getComponentType(), + arraySetters.get(aMethod))}); + } else { + aMethod.invoke(javaInstance, + new Object[] {createNonPrimitiveArray(paramType.getComponentType(), + arraySetters.get(aMethod))}); + } + } + } + } + + private Object createNonPrimitiveArray(Class fieldType, List values) { + Object objectArray = Array.newInstance(fieldType, values.size()); + for (int count = 0; count < values.size(); ++count) { + Array.set(objectArray, count, values.get(count)); + } + return objectArray; + } + + private Object createPrimitiveArray(Class fieldType, List values) { + if (fieldType.isPrimitive()) { + if (fieldType.getName().equals("int")) { + int[] primitiveValues = new int[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Integer) values.get(count)).intValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("float")) { + float[] primitiveValues = new float[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Float) values.get(count)).floatValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("boolean")) { + boolean[] primitiveValues = new boolean[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Boolean) values.get(count)).booleanValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("char")) { + char[] primitiveValues = new char[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Character) values.get(count)).charValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("byte")) { + byte[] primitiveValues = new byte[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Byte) values.get(count)).byteValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("short")) { + short[] primitiveValues = new short[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Short) values.get(count)).shortValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("long")) { + long[] primitiveValues = new long[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Long) values.get(count)).longValue(); + } + return primitiveValues; + } else if (fieldType.getName().equals("double")) { + double[] primitiveValues = new double[values.size()]; + for (int count = 0; count < values.size(); ++count) { + primitiveValues[count] = ((Double) values.get(count)).doubleValue(); + } + return primitiveValues; + } + } + return values; + } + + public abstract String getText(T source) throws XML2JavaMapperException; + + public abstract List getChildElements(T parent) throws XML2JavaMapperException; + + public abstract String getElementName(T element) throws XML2JavaMapperException; + + public abstract boolean isTextElement(T element) throws XML2JavaMapperException; + + public abstract T getRootElement(T element) throws XML2JavaMapperException; + + public Class getTargetType() { + return Object.class; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.java new file mode 100644 index 0000000000..dfdd54084b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/javabeans/XML2JavaMapperException.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.core.databinding.javabeans; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * This exception is used to encapsulate and rethrow exceptions that arise out + * of converting XML Data to Java Objects. + */ +public class XML2JavaMapperException extends TuscanyRuntimeException { + private static final long serialVersionUID = 6596530102591630642L; + + private QName xmlElementName; + private String javaFieldName; + private Class javaType; + + public XML2JavaMapperException(String message) { + super(message); + } + + public XML2JavaMapperException(Throwable cause) { + super(cause); + } + + public QName getXmlElementName() { + return xmlElementName; + } + + public void setXmlElementName(QName xmlElementName) { + this.xmlElementName = xmlElementName; + } + + public String getJavaFieldName() { + return javaFieldName; + } + + public void setJavaFieldName(String javaFieldName) { + this.javaFieldName = javaFieldName; + } + + public Class getJavaType() { + return javaType; + } + + public void setJavaType(Class javaType) { + this.javaType = javaType; + } + + @Override + public String getMessage() { + return super.getMessage() + " <" + getJavaFieldName() + "> " + " in <" + getJavaType() + ">"; + } + + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/BeanUtil.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/BeanUtil.java new file mode 100644 index 0000000000..34e3e07843 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/BeanUtil.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.TypeInfo; + +public final class BeanUtil { + private static final Object[] NULL = (Object[])null; + private static int nsCount = 1; + + private static final SimpleTypeMapperExtension MAPPER = new SimpleTypeMapperExtension(); + + private BeanUtil() { + } + + private static boolean isSimpleType(Class javaType) { + return MAPPER.getXMLType(javaType) != null; + } + + private static String getStringValue(Object o) { + if (o == null) { + return null; + } + TypeInfo info = MAPPER.getXMLType(o.getClass()); + if (info != null) { + return MAPPER.toXMLLiteral(info.getQName(), o, null); + } else { + return String.valueOf(o); + } + } + + /** + * To Serilize Bean object this method is used, this will create an object + * array using given bean object + * + * @param beanObject + * @param beanName + */ + public static XMLStreamReader getXMLStreamReader(Object beanObject, QName beanName) { + try { + ClassLoader cl = beanObject.getClass().getClassLoader(); + if (cl == null) { + cl = ClassLoader.getSystemClassLoader(); + } + String beanNS = beanName.getNamespaceURI(); + String beanPrefix = beanName.getPrefix(); + BeanInfo beanInfo = Introspector.getBeanInfo(beanObject.getClass()); + PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors(); + Map propertMap = new HashMap(); + for (int i = 0; i < propDescs.length; i++) { + PropertyDescriptor propDesc = propDescs[i]; + propertMap.put(propDesc.getName(), propDesc); + } + List properties = new ArrayList(propertMap.keySet()); + Collections.sort(properties); + List props = new ArrayList(); + for (int i = 0; i < properties.size(); i++) { + String property = properties.get(i); + PropertyDescriptor propDesc = (PropertyDescriptor)propertMap.get(property); + if (propDesc == null) { + // JAM does bad thing so I need to add this + continue; + } + Class ptype = propDesc.getPropertyType(); + if ("class".equals(property)) { + continue; + } + if (isSimpleType(ptype)) { + Object value = propDesc.getReadMethod().invoke(beanObject, NULL); + NamedProperty prop = + new NamedProperty(new QName(beanNS, property, beanPrefix), getStringValue(value)); + props.add(prop); + } else if (ptype.isArray()) { + if (isSimpleType(ptype.getComponentType())) { + Object value = propDesc.getReadMethod().invoke(beanObject, NULL); + if (value != null) { + int i1 = Array.getLength(value); + for (int j = 0; j < i1; j++) { + Object o = Array.get(value, j); + NamedProperty prop = + new NamedProperty(new QName(beanNS, property, beanPrefix), getStringValue(o)); + props.add(prop); + } + } else { + NamedProperty prop = new NamedProperty(new QName(beanNS, property, beanPrefix), value); + props.add(prop); + } + + } else { + Object value[] = (Object[])propDesc.getReadMethod().invoke(beanObject, NULL); + if (value != null) { + for (int j = 0; j < value.length; j++) { + Object o = value[j]; + NamedProperty prop = + new NamedProperty(new QName(beanNS, property, beanPrefix), getStringValue(o)); + props.add(prop); + } + } else { + NamedProperty prop = new NamedProperty(new QName(beanNS, property, beanPrefix), value); + props.add(prop); + } + } + } else if (Collection.class.isAssignableFrom(ptype)) { + Object value = propDesc.getReadMethod().invoke(beanObject, NULL); + Collection objList = (Collection)value; + if (objList != null && objList.size() > 0) { + // this was given error , when the array.size = 0 + // and if the array contain simple type , then the + // ADBPullParser asked + // PullParser from That simpel type + for (Iterator j = objList.iterator(); j.hasNext();) { + Object o = j.next(); + if (isSimpleType(o.getClass())) { + NamedProperty prop = + new NamedProperty(new QName(beanNS, property, beanPrefix), getStringValue(o)); + props.add(prop); + } else { + NamedProperty prop = new NamedProperty(new QName(beanNS, property, beanPrefix), o); + props.add(prop); + } + } + + } else { + NamedProperty prop = new NamedProperty(new QName(beanNS, property, beanPrefix), value); + props.add(prop); + } + } else { + Object value = propDesc.getReadMethod().invoke(beanObject, NULL); + NamedProperty prop = new NamedProperty(new QName(beanNS, property, beanPrefix), value); + props.add(prop); + } + } + NamedProperty[] elements = new NamedProperty[props.size()]; + props.toArray(elements); + return new XMLFragmentStreamReaderImpl(beanName, elements, null); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + /** + * to get the pull parser for a given bean object , generate the wrpper + * element using class name + * + * @param beanObject + */ + public static XMLStreamReader getXMLStreamReader(Object beanObject) { + String className = beanObject.getClass().getName(); + if (className.indexOf(".") > 0) { + className = className.substring(className.lastIndexOf('.') + 1, className.length()); + } + return getXMLStreamReader(beanObject, new QName(className)); + } + + /** + * increments the namespace counter and returns a new prefix + * + * @return unique prefix + */ + public static String getUniquePrefix() { + return "s" + nsCount++; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java new file mode 100644 index 0000000000..a3f13663bc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + + +import org.w3c.dom.Node; + +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; + +/** + * DOM DataBinding + * + * @version $Rev$ $Date$ + */ +public class DOMDataBinding extends DataBindingExtension { + public static final String NAME = Node.class.getName(); + public static final String[] ALIASES = new String[] {"dom"}; + + public DOMDataBinding() { + super(NAME, ALIASES, Node.class); + } + + @Override + public WrapperHandler getWrapperHandler() { + return new DOMWrapperHandler(); + } + + public Object copy(Object source) { + if (Node.class.isAssignableFrom(source.getClass())) { + Node nodeSource = (Node) source; + return nodeSource.cloneNode(true); + } + return super.copy(source); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java new file mode 100644 index 0000000000..6aac20e98f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class DOMWrapperHandler implements WrapperHandler { + + private Document document; + + public DOMWrapperHandler() { + super(); + try { + this.document = DOMHelper.newDocument(); + } catch (ParserConfigurationException e) { + throw new TransformationException(e); + } + } + + public Node create(ElementInfo element, TransformationContext context) { + QName name = element.getQName(); + return DOMHelper.createElement(document, name); + } + + public void setChild(Node wrapper, int i, ElementInfo childElement, Object value) { + Node node = (Node) value; + if (node.getNodeType() == Node.DOCUMENT_NODE) { + node = ((Document) node).getDocumentElement(); + } + wrapper.appendChild(wrapper.getOwnerDocument().importNode(node, true)); + } + + public List getChildren(Node wrapper) { + assert wrapper != null; + if (wrapper.getNodeType() == Node.DOCUMENT_NODE) { + wrapper = ((Document) wrapper).getDocumentElement(); + } + List elements = new ArrayList(); + NodeList nodes = wrapper.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() == Node.ELEMENT_NODE) { + elements.add(node); + } + } + return elements; + } +} \ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java new file mode 100644 index 0000000000..39adcf332d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.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.core.databinding.xml; + +import static javax.xml.XMLConstants.DEFAULT_NS_PREFIX; +import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.w3c.dom.Attr; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class DOMXMLStreamReader extends XMLFragmentStreamReaderImpl { + private Element rootElement; + + public DOMXMLStreamReader(Node node) { + super(null); + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + this.rootElement = ((Document)node).getDocumentElement(); + break; + case Node.ELEMENT_NODE: + this.rootElement = (Element)node; + break; + default: + throw new IllegalArgumentException("Illegal Node"); + } + String ns = rootElement.getNamespaceURI(); + String prefix = rootElement.getPrefix(); + String name = rootElement.getLocalName(); + elementQName = new QName(ns == null ? "" : ns, name, prefix == null ? "" : prefix); + } + + @Override + protected final NamedProperty[] getAttributes() { + if (attributes == null) { + List attributeList = new ArrayList(); + NamedNodeMap nodeMap = rootElement.getAttributes(); + for (int i = 0; i < nodeMap.getLength(); i++) { + Attr attr = (Attr)nodeMap.item(i); + String ns = attr.getNamespaceURI(); + String prefix = attr.getPrefix(); + if (!XMLNS_ATTRIBUTE_NS_URI.equals(ns)) { + QName attrName = new QName(ns == null ? "" : ns, attr.getLocalName(), prefix != null ? prefix : ""); + NamedProperty pair = new NamedProperty(attrName, attr.getValue()); + attributeList.add(pair); + } + } + attributes = new NamedProperty[attributeList.size()]; + attributeList.toArray(attributes); + } + return attributes; + } + + @Override + protected QName[] getNamespaces() { + List nsList = new ArrayList(); + NamedNodeMap nodeMap = rootElement.getAttributes(); + for (int i = 0; i < nodeMap.getLength(); i++) { + Attr attr = (Attr)nodeMap.item(i); + String ns = attr.getNamespaceURI(); + if (XMLNS_ATTRIBUTE_NS_URI.equals(ns)) { + String prefix = attr.getPrefix(); + if (prefix == null) { + // xmlns="http://ns" + nsList.add(new QName(attr.getValue(), "", DEFAULT_NS_PREFIX)); + } else { + // xmlns:ns="http://ns" + nsList.add(new QName(attr.getValue(), "", attr.getLocalName())); + } + } + } + QName[] nss = new QName[nsList.size()]; + nsList.toArray(nss); + return nss; + } + + @Override + protected NamedProperty[] getElements() { + if (elements == null) { + List elementList = new ArrayList(); + NodeList nodeList = rootElement.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + switch (node.getNodeType()) { + case Node.TEXT_NODE: + case Node.CDATA_SECTION_NODE: + NamedProperty pair = new NamedProperty(ELEMENT_TEXT, ((CharacterData)node).getData()); + elementList.add(pair); + break; + + case Node.ELEMENT_NODE: + Element element = (Element)node; + QName elementName = new QName(element.getNamespaceURI(), element.getLocalName()); + pair = new NamedProperty(elementName, new DOMXMLStreamReader(element)); + elementList.add(pair); + break; + } + } + elements = new NamedProperty[elementList.size()]; + elementList.toArray(elements); + } + return elements; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DelegatingNamespaceContext.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DelegatingNamespaceContext.java new file mode 100644 index 0000000000..1edc52c089 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DelegatingNamespaceContext.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.core.databinding.xml; + +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.Iterator; +import java.util.List; + +import javax.xml.namespace.NamespaceContext; + +public class DelegatingNamespaceContext implements NamespaceContext { + private static int count; + + private class WrappingIterator implements Iterator { + + private Iterator containedIterator; + + public WrappingIterator(Iterator containedIterator) { + this.containedIterator = containedIterator; + } + + public Iterator getContainedIterator() { + return containedIterator; + } + + public boolean hasNext() { + return containedIterator.hasNext(); + } + + public Object next() { + return containedIterator.next(); + } + + /** + * As per the contract on the API of Namespace context the returned iterator should be immutable + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + public void setContainedIterator(Iterator containedIterator) { + this.containedIterator = containedIterator; + } + } + + private NamespaceContext parentNsContext; + + private FastStack prefixStack = new FastStack(); + + // Keep two arraylists for the prefixes and namespaces. They should be in + // sync + // since the index of the entry will be used to relate them + // use the minimum initial capacity to let things handle memory better + + private FastStack uriStack = new FastStack(); + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @return string + */ + public String generateUniquePrefix() { + String prefix = "p" + count++; + // null should be returned if the prefix is not bound! + while (getNamespaceURI(prefix) != null) { + prefix = "p" + count++; + } + + return prefix; + } + + public String getNamespaceURI(String prefix) { + // do the corrections as per the javadoc + int index = prefixStack.search(prefix); + if (index != -1) { + return (String)uriStack.get(index); + } + if (parentNsContext != null) { + return parentNsContext.getPrefix(prefix); + } + return null; + } + + public NamespaceContext getParentNsContext() { + return parentNsContext; + } + + public String getPrefix(String uri) { + // do the corrections as per the javadoc + int index = uriStack.search(uri); + if (index != -1) { + return (String)prefixStack.get(index); + } + + if (parentNsContext != null) { + return parentNsContext.getPrefix(uri); + } + return null; + } + + public Iterator getPrefixes(String uri) { + // create an arraylist that contains the relevant prefixes + String[] uris = (String[])uriStack.toArray(new String[uriStack.size()]); + List tempList = new ArrayList(); + for (int i = uris.length - 1; i >= 0; i--) { + if (uris[i].equals(uri)) { + tempList.add(prefixStack.get(i)); + // we assume that array conversion preserves the order + } + } + // by now all the relevant prefixes are collected + // make a new iterator and provide a wrapper iterator to + // obey the contract on the API + return new WrappingIterator(tempList.iterator()); + } + + /** + * Pop a namespace + */ + public void popNamespace() { + prefixStack.pop(); + uriStack.pop(); + } + + /** + * Register a namespace in this context + * + * @param prefix + * @param uri + */ + public void pushNamespace(String prefix, String uri) { + prefixStack.push(prefix); + uriStack.push(uri); + + } + + public void setParentNsContext(NamespaceContext parentNsContext) { + this.parentNsContext = parentNsContext; + } + + /** + * An implementation of the {@link java.util.Stack} API that is based on an ArrayList instead of a + * Vector, so it is not synchronized to protect against multi-threaded access. The implementation is + * therefore operates faster in environments where you do not need to worry about multiple thread contention. + *

+ * The removal order of an ArrayStack is based on insertion order: The most recently added element is + * removed first. The iteration order is not the same as the removal order. The iterator returns elements + * from the bottom up, whereas the {@link #remove()} method removes them from the top down. + *

+ * Unlike Stack, ArrayStack accepts null entries. + */ + public static class FastStack extends ArrayList { + + /** Ensure serialization compatibility */ + private static final long serialVersionUID = 2130079159931574599L; + + /** + * Constructs a new empty ArrayStack. The initial size is controlled by ArrayList + * and is currently 10. + */ + public FastStack() { + super(); + } + + /** + * Constructs a new empty ArrayStack with an initial size. + * + * @param initialSize the initial size to use + * @throws IllegalArgumentException if the specified initial size is negative + */ + public FastStack(int initialSize) { + super(initialSize); + } + + /** + * Return true if this stack is currently empty. + *

+ * This method exists for compatibility with java.util.Stack. New users of this class should use + * isEmpty instead. + * + * @return true if the stack is currently empty + */ + public boolean empty() { + return isEmpty(); + } + + /** + * Returns the top item off of this stack without removing it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T peek() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return get(n - 1); + } + } + + /** + * Returns the n'th item down (zero-relative) from the top of this stack without removing it. + * + * @param n the number of items down to go + * @return the n'th item on the stack, zero relative + * @throws EmptyStackException if there are not enough items on the stack to satisfy this request + */ + public T peek(int n) throws EmptyStackException { + int m = (size() - n) - 1; + if (m < 0) { + throw new EmptyStackException(); + } else { + return get(m); + } + } + + /** + * Pops the top item off of this stack and return it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T pop() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return remove(n - 1); + } + } + + /** + * Pushes a new item onto the top of this stack. The pushed item is also returned. This is equivalent to calling + * add. + * + * @param item the item to be added + * @return the item just pushed + */ + public Object push(T item) { + add(item); + return item; + } + + /** + * Returns the top-most index for the object in the stack + * + * @param object the object to be searched for + * @return top-most index, or -1 if not found + */ + public int search(T object) { + int i = size() - 1; // Current index + while (i >= 0) { + T current = get(i); + if ((object == null && current == null) || (object != null && object.equals(current))) { + return i; + } + i--; + } + return -1; + } + + /** + * Returns the element on the top of the stack. + * + * @return the element on the top of the stack + * @throws EmptyStackException if the stack is empty + */ + public T get() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return get(size - 1); + } + + /** + * Removes the element on the top of the stack. + * + * @return the removed element + * @throws EmptyStackException if the stack is empty + */ + public T remove() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return remove(size - 1); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java new file mode 100644 index 0000000000..e9757fa13c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + */ +@Service(Transformer.class) +public class InputSource2Node extends TransformerExtension implements + PullTransformer { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputSource source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source.getCharacterStream()); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputSource.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java new file mode 100644 index 0000000000..be78a07ede --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputSource to SAX + */ +@Service(Transformer.class) +public class InputSource2SAX extends TransformerExtension implements + PushTransformer { + + public void transform(InputSource source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); + reader.setContentHandler(target); + reader.parse(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputSource.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java new file mode 100644 index 0000000000..e103c82b33 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + */ +@Service(Transformer.class) +public class InputStream2Node extends TransformerExtension implements + PullTransformer { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputStream source, TransformationContext context) { + try { + Source streamSource = new SAXSource(new InputSource(source)); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputStream.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java new file mode 100644 index 0000000000..d74863ea95 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.InputStream; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputStream to SAX + */ +@Service(Transformer.class) +public class InputStream2SAX extends TransformerExtension implements + PushTransformer { + public void transform(InputStream source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setContentHandler(target); + reader.parse(new InputSource(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputStream.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValueArrayStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValueArrayStreamReader.java new file mode 100644 index 0000000000..d10af29b35 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValueArrayStreamReader.java @@ -0,0 +1,403 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class NameValueArrayStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 1; + private static final int END_ELEMENT_STATE = 2; + private static final int FINAL_END_ELEMENT_STATE = 3; + private static final int START_ELEMENT_STATE_WITH_NULL = 4; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + // the index of the array + private int arrayIndex; + + private QName name; + private String[] values; + + // start element is the default state + private int state = START_ELEMENT_STATE; + + public NameValueArrayStreamReader(QName name, String[] values) { + this.name = name; + this.values = values; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParentNsContext(nsContext); + } + + public void init() { + // todo what if the Qname namespace has not been declared + } + + public Object getProperty(String string) throws IllegalArgumentException { + return null; + } + + /** + * @throws XMLStreamException + */ + public int next() throws XMLStreamException { + switch (state) { + case START_ELEMENT_STATE: + if (values.length > 0) { + state = TEXT_STATE; + return CHARACTERS; + } else { + state = FINAL_END_ELEMENT_STATE; + return END_ELEMENT; + } + + case START_ELEMENT_STATE_WITH_NULL: + if (arrayIndex == (values.length - 1)) { + state = FINAL_END_ELEMENT_STATE; + } else { + state = END_ELEMENT_STATE; + } + return END_ELEMENT; + case FINAL_END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case END_ELEMENT_STATE: + // we've to have more values since this is not the + // last value + // increment the counter + arrayIndex++; + if (values[arrayIndex] == null) { + state = START_ELEMENT_STATE_WITH_NULL; + } else { + state = START_ELEMENT_STATE; + } + return START_ELEMENT; + case TEXT_STATE: + if (arrayIndex == (values.length - 1)) { + state = FINAL_END_ELEMENT_STATE; + return END_ELEMENT; + } else { + state = END_ELEMENT_STATE; + return END_ELEMENT; + } + + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing done here + } + + public String getElementText() throws XMLStreamException { + return null; // not implemented + } + + public int nextTag() throws XMLStreamException { + return 0; // not implemented + } + + public String getAttributeValue(String string, String string1) { + if (state == TEXT_STATE) { + // todo something + return null; + } else { + return null; + } + + } + + public int getAttributeCount() { + if (state == START_ELEMENT_STATE_WITH_NULL) { + return 1; + } + if (state == START_ELEMENT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + + } + + public QName getAttributeName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getNamespaceURI(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getLocalPart(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getPrefix(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not implemented + } + + public String getAttributeValue(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_VALUE_TRUE; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public int getNamespaceCount() { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent()) { + return 1; + } else { + return 0; + } + + } + + public String getNamespacePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return NIL_QNAME.getPrefix(); + } else { + return null; + } + } + + public String getNamespaceURI(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return NIL_QNAME.getNamespaceURI(); + } else { + return null; + } + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public boolean isDone() { + return state == FINAL_END_ELEMENT_STATE; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + case FINAL_END_ELEMENT_STATE: + return END_ELEMENT; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return values[arrayIndex]; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return values[arrayIndex].toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return values[arrayIndex].length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return null; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public Location getLocation() { + return null; // not supported + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // todo 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean hasNext() throws XMLStreamException { + return state != FINAL_END_ELEMENT_STATE; + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + /** + * Test whether the xsi namespace is present + */ + private boolean isXsiNamespacePresent() { + return namespaceContext.getNamespaceURI(NIL_QNAME.getPrefix()) != null; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValuePairStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValuePairStreamReader.java new file mode 100644 index 0000000000..d9261b8b4f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NameValuePairStreamReader.java @@ -0,0 +1,347 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + + +public class NameValuePairStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 1; + private static final int END_ELEMENT_STATE = 2; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + + private QName name; + private String value; + + private int state = START_ELEMENT_STATE; + // initiate at the start element state + + // keeps track whether the namespace is declared + // false by default + private boolean nsDeclared; + + public NameValuePairStreamReader(QName name, String value) { + this.name = name; + this.value = value; + } + + public Object getProperty(String key) throws IllegalArgumentException { + return null; + } + + public int next() throws XMLStreamException { + // no need to handle null here. it should have been handled + // already + switch (state) { + case START_ELEMENT_STATE: + state = TEXT_STATE; + return CHARACTERS; + case END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case TEXT_STATE: + state = END_ELEMENT_STATE; + return END_ELEMENT; + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // not implemented + } + + public String getElementText() throws XMLStreamException { + if (state == START_ELEMENT) { + // move to the end state and return the value + state = END_ELEMENT_STATE; + return value; + } else { + throw new XMLStreamException(); + } + + } + + public int nextTag() throws XMLStreamException { + return 0; // todo + } + + public boolean hasNext() throws XMLStreamException { + return state != END_ELEMENT_STATE; + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + public String getAttributeValue(String string, String string1) { + return null; + } + + public int getAttributeCount() { + return 0; + } + + public QName getAttributeName(int i) { + return null; + } + + public String getAttributeNamespace(int i) { + return null; + } + + public String getAttributeLocalName(int i) { + return null; + } + + public String getAttributePrefix(int i) { + return null; + } + + public String getAttributeType(int i) { + return null; + } + + public String getAttributeValue(int i) { + return null; + } + + public boolean isAttributeSpecified(int i) { + return false; // no attribs here + } + + public int getNamespaceCount() { + return nsDeclared ? 1 : 0; + } + + public String getNamespacePrefix(int i) { + return (nsDeclared && i == 0) ? name.getPrefix() : null; + } + + public String getNamespaceURI(int i) { + return (nsDeclared && i == 0) ? name.getNamespaceURI() : null; + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return value; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return value.toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return value.length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return null; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public Location getLocation() { + return new Location() { + public int getLineNumber() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getCharacterOffset() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // todo 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean isDone() { + return state == END_ELEMENT_STATE; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParentNsContext(nsContext); + } + + public void init() { + // just add the current elements namespace and prefix to the this + // elements nscontext + addToNsMap(name.getPrefix(), name.getNamespaceURI()); + + } + + /** + * @param prefix + * @param uri + */ + private void addToNsMap(String prefix, String uri) { + // todo - need to fix this up to cater for cases where + // namespaces are having no prefixes + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + // this namespace is not there. Need to declare it + namespaceContext.pushNamespace(prefix, uri); + nsDeclared = true; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NamedProperty.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NamedProperty.java new file mode 100644 index 0000000000..0ce249e912 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NamedProperty.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * A named property + * + * @version $Rev$ $Date$ + */ +public class NamedProperty implements Map.Entry { + private QName key; + + private Object value; + + public NamedProperty(QName key, Object value) { + this.key = key; + this.value = value; + } + + public NamedProperty(String key, Object value) { + this.key = new QName(key); + this.value = value; + } + + public QName getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object value) { + Object v = this.value; + this.value = value; + return v; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NilElementStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NilElementStreamReader.java new file mode 100644 index 0000000000..8a454c8342 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/NilElementStreamReader.java @@ -0,0 +1,279 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class NilElementStreamReader implements XMLFragmentStreamReader { + + private static final int END_ELEMENT_STATE = 2; + + private static final int START_ELEMENT_STATE = 1; + private int currentState = START_ELEMENT; + + private QName elementQName; + + public NilElementStreamReader(QName elementQName) { + this.elementQName = elementQName; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // NOOP + } + + public void close() throws XMLStreamException { + // do nothing + } + + public int getAttributeCount() { + return 1; + } + + public String getAttributeLocalName(int i) { + return (i == 0) ? NIL_QNAME.getLocalPart() : null; + } + + public QName getAttributeName(int i) { + return (i == 0) ? NIL_QNAME : null; + } + + public String getAttributeNamespace(int i) { + return (i == 0) ? NIL_QNAME.getNamespaceURI() : null; + } + + public String getAttributePrefix(int i) { + return (i == 0) ? NIL_QNAME.getPrefix() : null; + } + + public String getAttributeType(int i) { + throw new UnsupportedOperationException(); + } + + public String getAttributeValue(int i) { + return (i == 0) ? NIL_VALUE_TRUE : null; + } + + public String getAttributeValue(String string, String string1) { + if (string == null && NIL_QNAME.getLocalPart().equals(string1)) { + return NIL_VALUE_TRUE; + } + return null; + } + + public String getCharacterEncodingScheme() { + throw new UnsupportedOperationException(); + } + + public String getElementText() throws XMLStreamException { + return null; + } + + public String getEncoding() { + return null; + } + + public int getEventType() { + int returnEvent = START_DOCUMENT; + switch (currentState) { + case START_ELEMENT_STATE: + returnEvent = START_ELEMENT; + break; + case END_ELEMENT_STATE: + returnEvent = END_ELEMENT; + break; + } + return returnEvent; + } + + public String getLocalName() { + return elementQName.getLocalPart(); + } + + public Location getLocation() { + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + return elementQName; + } + + public NamespaceContext getNamespaceContext() { + throw new UnsupportedOperationException(); + } + + public int getNamespaceCount() { + return 0; + } + + public String getNamespacePrefix(int i) { + return null; + } + + public String getNamespaceURI() { + return elementQName.getNamespaceURI(); + } + + public String getNamespaceURI(int i) { + return null; + } + + public String getNamespaceURI(String string) { + if (elementQName.getPrefix() != null && elementQName.getPrefix().equals(string)) { + return elementQName.getNamespaceURI(); + } else { + return null; + } + } + + public String getPIData() { + throw new UnsupportedOperationException(); + } + + public String getPITarget() { + throw new UnsupportedOperationException(); + } + + public String getPrefix() { + return elementQName.getPrefix(); + } + + public Object getProperty(String key) throws IllegalArgumentException { + // since optimization is a global property + // we've to implement it everywhere + return null; + } + + public String getText() { + return null; + } + + public char[] getTextCharacters() { + return new char[0]; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + return 0; + } + + public int getTextLength() { + return 0; + } + + public int getTextStart() { + return 0; + } + + public String getVersion() { + throw new UnsupportedOperationException(); + } + + public boolean hasName() { + return true; + } + + public boolean hasNext() throws XMLStreamException { + return currentState != END_ELEMENT_STATE; + + } + + public boolean hasText() { + return false; + } + + public void init() { + // NOOP + } + + public boolean isAttributeSpecified(int i) { + return i == 0; + } + + public boolean isCharacters() { + return false; + } + + public boolean isDone() { + return currentState == END_ELEMENT_STATE; + } + + public boolean isEndElement() { + return currentState == END_ELEMENT_STATE; + } + + public boolean isStandalone() { + throw new UnsupportedOperationException(); + } + + public boolean isStartElement() { + return currentState == START_ELEMENT_STATE; + } + + public boolean isWhiteSpace() { + return false; + } + + public int next() throws XMLStreamException { + int returnEvent = START_DOCUMENT; + switch (currentState) { + case START_ELEMENT_STATE: + currentState = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + break; + case END_ELEMENT_STATE: + throw new XMLStreamException("parser completed!"); + + } + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing + } + + public boolean standaloneSet() { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java new file mode 100644 index 0000000000..34fbdf8c6f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.OutputStream; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Push DOM Node to OutputStream + */ +@Service(Transformer.class) +public class Node2OutputStream extends TransformerExtension implements + PushTransformer { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, OutputStream writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return OutputStream.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java new file mode 100755 index 0000000000..92378e96a3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.StringWriter; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML String + */ +@Service(org.apache.tuscany.spi.databinding.Transformer.class) +public class Node2String extends TransformerExtension implements PullTransformer { + private static final Node2Writer TRANSFORMER = new Node2Writer(); + + public String transform(Node source, TransformationContext context) { + try { + StringWriter writer = new StringWriter(); + TRANSFORMER.transform(source, writer, context); + return writer.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return String.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java new file mode 100644 index 0000000000..96328fdd2f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Writer; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Push DOM Node to Writer + */ +@Service(Transformer.class) +public class Node2Writer extends TransformerExtension implements PushTransformer { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, Writer writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return Writer.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java new file mode 100644 index 0000000000..0c75826ffa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML XMLStreamReader + */ +@Service(Transformer.class) +public class Node2XMLStreamReader extends TransformerExtension implements + PullTransformer { + + public XMLStreamReader transform(Node source, TransformationContext context) { + try { + DOMXMLStreamReader reader = new DOMXMLStreamReader(source); + return new XMLDocumentStreamReader(reader); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return XMLStreamReader.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java new file mode 100644 index 0000000000..02de055c35 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Reader; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Push DOM Reader to Node + */ +@Service(Transformer.class) +public class Reader2Node extends TransformerExtension implements PullTransformer { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(Reader source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Reader.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java new file mode 100644 index 0000000000..0a4504b3de --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Reader; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + */ +@Service(Transformer.class) +public class Reader2SAX extends TransformerExtension implements + PushTransformer { + public void transform(Reader source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(source), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Reader.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java new file mode 100644 index 0000000000..8f8f0f952e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java @@ -0,0 +1,244 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; + +/** + * SAX2DOM adapter + */ +public class SAX2DOM implements ContentHandler, LexicalHandler { + public static final String EMPTYSTRING = ""; + public static final String XML_PREFIX = "xml"; + public static final String XMLNS_PREFIX = "xmlns"; + public static final String XMLNS_STRING = "xmlns:"; + public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; + + private Node root; + + private Document document; + + private Node nextSibling; + + private Stack nodeStk = new Stack(); + + private List namespaceDecls; + + private Node lastSibling; + + public SAX2DOM() throws ParserConfigurationException { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + public SAX2DOM(Node root, Node nextSibling) throws ParserConfigurationException { + this.root = root; + if (root instanceof Document) { + this.document = (Document)root; + } else if (root != null) { + this.document = root.getOwnerDocument(); + } else { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + this.nextSibling = nextSibling; + } + + public SAX2DOM(Node root) throws ParserConfigurationException { + this(root, null); + } + + public Node getDOM() { + return root; + } + + public void characters(char[] ch, int start, int length) { + final Node last = (Node)nodeStk.peek(); + + // No text nodes can be children of root (DOM006 exception) + if (last != document) { + final String text = new String(ch, start, length); + if (lastSibling != null && lastSibling.getNodeType() == Node.TEXT_NODE) { + ((Text)lastSibling).appendData(text); + } else if (last == root && nextSibling != null) { + lastSibling = last.insertBefore(document.createTextNode(text), nextSibling); + } else { + lastSibling = last.appendChild(document.createTextNode(text)); + } + + } + } + + public void startDocument() { + nodeStk.push(root); + } + + public void endDocument() { + nodeStk.pop(); + } + + public void startElement(String namespace, String localName, String qName, Attributes attrs) { + final Element tmp = (Element)document.createElementNS(namespace, qName); + + // Add namespace declarations first + if (namespaceDecls != null) { + final int nDecls = namespaceDecls.size(); + for (int i = 0; i < nDecls; i++) { + final String prefix = (String)namespaceDecls.get(i++); + + if (prefix == null || prefix.equals(EMPTYSTRING)) { + tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, (String)namespaceDecls.get(i)); + } else { + tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, (String)namespaceDecls.get(i)); + } + } + namespaceDecls.clear(); + } + + // Add attributes to element + final int nattrs = attrs.getLength(); + for (int i = 0; i < nattrs; i++) { + if (attrs.getLocalName(i) == null) { + tmp.setAttribute(attrs.getQName(i), attrs.getValue(i)); + } else { + tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i)); + } + } + + // Append this new node onto current stack node + Node last = (Node)nodeStk.peek(); + + // If the SAX2DOM is created with a non-null next sibling node, + // insert the result nodes before the next sibling under the root. + if (last == root && nextSibling != null) { + last.insertBefore(tmp, nextSibling); + } else { + last.appendChild(tmp); + } + + // Push this node onto stack + nodeStk.push(tmp); + lastSibling = null; + } + + public void endElement(String namespace, String localName, String qName) { + nodeStk.pop(); + lastSibling = null; + } + + public void startPrefixMapping(String prefix, String uri) { + if (namespaceDecls == null) { + namespaceDecls = new ArrayList(2); + } + namespaceDecls.add(prefix); + namespaceDecls.add(uri); + } + + public void endPrefixMapping(String prefix) { + // do nothing + } + + /** + * This class is only used internally so this method should never be called. + */ + public void ignorableWhitespace(char[] ch, int start, int length) { + } + + /** + * adds processing instruction node to DOM. + */ + public void processingInstruction(String target, String data) { + final Node last = (Node)nodeStk.peek(); + ProcessingInstruction pi = document.createProcessingInstruction(target, data); + if (pi != null) { + if (last == root && nextSibling != null) { + last.insertBefore(pi, nextSibling); + } else { + last.appendChild(pi); + } + + lastSibling = pi; + } + } + + /** + * This class is only used internally so this method should never be called. + */ + public void setDocumentLocator(Locator locator) { + } + + /** + * This class is only used internally so this method should never be called. + */ + public void skippedEntity(String name) { + } + + /** + * Lexical Handler method to create comment node in DOM tree. + */ + public void comment(char[] ch, int start, int length) { + final Node last = (Node)nodeStk.peek(); + Comment comment = document.createComment(new String(ch, start, length)); + if (comment != null) { + if (last == root && nextSibling != null) { + last.insertBefore(comment, nextSibling); + } else { + last.appendChild(comment); + } + + lastSibling = comment; + } + } + + // Lexical Handler methods- not implemented + public void startCDATA() { + } + + public void endCDATA() { + } + + public void startEntity(java.lang.String name) { + } + + public void endDTD() { + } + + public void endEntity(String name) { + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java new file mode 100644 index 0000000000..79118b4a2c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +@Service(Transformer.class) +public class SAX2DOMPipe extends TransformerExtension implements + DataPipe { + private SAX2DOM pipe; + + /** + * + */ + public SAX2DOMPipe() { + super(); + try { + this.pipe = new SAX2DOM(); + } catch (ParserConfigurationException e) { + throw new IllegalArgumentException(e); + } + } + + public Node getResult() { + return pipe.getDOM(); + } + + public Class getTargetType() { + return Node.class; + } + + public ContentHandler getSink() { + return pipe; + } + + public Class getSourceType() { + return ContentHandler.class; + } + + public int getWeight() { + return 30; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java new file mode 100755 index 0000000000..7db14efb39 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +/** + * Transform TrAX Source to Result + */ +@Service(org.apache.tuscany.spi.databinding.Transformer.class) +public class Source2ResultTransformer extends TransformerExtension implements + PushTransformer { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public void transform(Source source, Result result, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + transformer.transform(source, result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Source.class; + } + + public Class getTargetType() { + return Result.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java new file mode 100644 index 0000000000..63fa53edb4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Adapter that converts from StAX to SAX event streams. Currently the following + * SAX events are not generated: + *

    + *
  • ignorableWhitespace
  • + *
  • skippedEntity
  • + *
      + * Also the following StAX events are not mapped: + *
        + *
      • CDATA
      • + *
      • COMMENT
      • + *
      • DTD
      • + *
      • ENTITY_DECLARATION
      • + *
      • ENTITY_REFERENCE
      • + *
      • NOTATION_DECLARATION
      • + *
      • SPACE
      • + *
      + * StAX ATTRIBUTE events are ignored but the equivalent attributes (derived from + * the START_ELEMENT event) are supplied in the SAX startElement event's + * Attributes parameter. If the adaptor is configured to pass namespace prefixes + * then namespace information will also be included in the Attributes; StAX + * NAMESPACE events are ignored.

      Another issue is namespace processing. If + * the reader is positioned at a sub-node, we cannot capture all the in-scope + * namespace bindings. Therefore we cannot re-create a proper SAX event stream + * from a StAX parser.

      For example

      <a:root xmlns:a="foo" + * xmlns:b="bar"><b:sub>a:foo</b:sub></a:root>

      And if + * you are handed a parser at <b:sub>, then your SAX events should look + * like:

      <b:sub xmlns:a="foo" xmlns:b="bar">a:foo</b:sub>

      + * not:

      <b:sub>a:foo</b:sub>

      Proposal: we change the + * receiver of SAX events (SDOXMLResourceImpl) so that it uses NamespaceContext + * to resolve prefix (as opposed to record start/endPrefixMappings and use it + * for resolution.) + * + * @version $Rev$ $Date$ + */ +public class StAX2SAXAdapter { + private final boolean namespacePrefixes; + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event stream + * into a SAX event stream. + * + * @param namespacePrefixes whether xmlns attributes should be included in + * startElement events; + */ + public StAX2SAXAdapter(boolean namespacePrefixes) { + this.namespacePrefixes = namespacePrefixes; + } + + /** + * Pull events from the StAX stream and dispatch to the SAX ContentHandler. + * The StAX stream would typically be located on a START_DOCUMENT or + * START_ELEMENT event and when this method returns it will be located on + * the associated END_DOCUMENT or END_ELEMENT event. Behaviour with other + * start events is undefined. + * + * @param reader StAX event source to read + * @param handler SAX ContentHandler for processing events + * @throws XMLStreamException if there was a problem reading the stream + * @throws SAXException passed through from the ContentHandler + */ + public void parse(XMLStreamReader reader, ContentHandler handler) throws XMLStreamException, SAXException { + handler.setDocumentLocator(new LocatorAdaptor(reader.getLocation())); + + // remembers the nest level of elements to know when we are done + int level = 0; + int event = reader.getEventType(); + while (true) { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(reader, handler); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(reader.getPITarget(), reader.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + handler.characters(reader.getTextCharacters(), reader.getTextStart(), reader + .getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(reader, handler); + level--; + if (level == 0) { + return; + } + break; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + return; + /* + * uncomment to handle all events rather than just mapped + * ones // StAX events that are not mapped to SAX case + * XMLStreamConstants.COMMENT: case + * XMLStreamConstants.SPACE: case + * XMLStreamConstants.ENTITY_REFERENCE: case + * XMLStreamConstants.DTD: case XMLStreamConstants.CDATA: + * case XMLStreamConstants.NOTATION_DECLARATION: case + * XMLStreamConstants.ENTITY_DECLARATION: break; // StAX + * events handled in START_ELEMENT case + * XMLStreamConstants.ATTRIBUTE: case + * XMLStreamConstants.NAMESPACE: break; default: throw new + * AssertionError("Unknown StAX event: " + event); + */ + } + event = reader.next(); + } + } + + private void handleStartElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // send startPrefixMapping events immediately before startElement event + int nsCount = reader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, reader.getNamespaceURI(i)); + } + + // fire startElement + QName qname = reader.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(reader); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + private static void handleEndElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // fire endElement + QName qname = reader.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not + // actually required by SAX + int nsCount = reader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes(XMLStreamReader reader) { + assert reader.getEventType() == XMLStreamConstants.START_ELEMENT; + + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations if required + if (namespacePrefixes) { + for (int i = 0; i < reader.getNamespaceCount(); i++) { + String prefix = reader.getNamespacePrefix(i); + String uri = reader.getNamespaceURI(i); + attrs.addAttribute(null, prefix, "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < reader.getAttributeCount(); i++) { + String uri = reader.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = reader.getAttributeLocalName(i); + String prefix = reader.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = reader.getAttributeType(i); + String value = reader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adaptor for mapping Locator information. + */ + private static final class LocatorAdaptor implements Locator { + private final Location location; + + private LocatorAdaptor(Location location) { + this.location = location; + } + + public int getColumnNumber() { + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + return location == null ? "" : location.getSystemId(); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXDataBinding.java new file mode 100644 index 0000000000..f21e4f3734 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXDataBinding.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.lang.annotation.Annotation; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.DataType; + +/** + * A DataBinding for the StAX + * + * @version $Rev$ $Date$ + */ +public class StAXDataBinding extends DataBindingExtension { + public static final String NAME = XMLStreamReader.class.getName(); + public static final String[] ALIASES = new String[] {"stax"}; + + public StAXDataBinding() { + super(NAME, ALIASES, XMLStreamReader.class); + } + + public boolean introspect(DataType type, Annotation[] annotations) { + if (super.introspect(type, annotations)) { + type.setLogical(XMLType.UNKNOWN); + return true; + } else { + return false; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java new file mode 100755 index 0000000000..3ce9ca1144 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.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.core.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import 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 javax.xml.transform.Source; + + +public final class StAXHelper { + private static final XMLInputFactory INPUT_FACTORY = XMLInputFactory.newInstance(); + private static final XMLOutputFactory OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + + private StAXHelper() { + } + + public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(inputStream); + } + + public static XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(reader); + } + + public static XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(source); + } + + public static XMLStreamReader createXMLStreamReader(String string) throws XMLStreamException { + StringReader reader = new StringReader(string); + return createXMLStreamReader(reader); + } + + public static String save(XMLStreamReader reader) throws XMLStreamException { + StringWriter writer = new StringWriter(); + save(reader, writer); + return writer.toString(); + } + + public static void save(XMLStreamReader reader, OutputStream outputStream) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(outputStream); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, Writer writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(writer); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + serializer.serialize(reader, writer); + writer.flush(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java new file mode 100755 index 0000000000..d0b6ce07f2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class StreamDataPipe extends TransformerExtension implements + DataPipe { + + private ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + public InputStream getResult() { + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + public Class getTargetType() { + return InputStream.class; + } + + public int getWeight() { + return 50; + } + + public OutputStream getSink() { + return outputStream; + } + + public Class getSourceType() { + return OutputStream.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java new file mode 100755 index 0000000000..3f878a07b9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +@Service(Transformer.class) +public class String2Node extends TransformerExtension implements PullTransformer { + + public Node transform(String source, TransformationContext context) { + try { + DocumentBuilder builder = DOMHelper.newDocumentBuilder(); + InputSource inputSource = new InputSource(new StringReader(source)); + return builder.parse(inputSource); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return String.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java new file mode 100644 index 0000000000..50ea110b17 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.StringReader; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + */ +@Service(Transformer.class) +public class String2SAX extends TransformerExtension implements + PushTransformer { + + public void transform(String source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(new StringReader(source)), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return String.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java new file mode 100755 index 0000000000..9793cc3f7e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class String2XMLStreamReader extends TransformerExtension implements + PullTransformer { + + public XMLStreamReader transform(String source, TransformationContext context) { + try { + return StAXHelper.createXMLStreamReader(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return String.class; + } + + public Class getTargetType() { + return XMLStreamReader.class; + } + + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/WrappingXMLStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/WrappingXMLStreamReader.java new file mode 100644 index 0000000000..6fa6478bf0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/WrappingXMLStreamReader.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamReader; +import javax.xml.namespace.QName; +import javax.xml.namespace.NamespaceContext; + +public class WrappingXMLStreamReader implements XMLFragmentStreamReader { + + private XMLStreamReader reader; + + public WrappingXMLStreamReader(XMLStreamReader reader) { + this.reader = reader; + } + + public boolean isDone() { + try { + return !hasNext(); + } catch (XMLStreamException e) { + throw new RuntimeException(e); + } + } + + public Object getProperty(String string) throws IllegalArgumentException { + return reader.getProperty(string); + } + + public int next() throws XMLStreamException { + return reader.next(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing to do + } + + public String getElementText() throws XMLStreamException { + return reader.getElementText(); + } + + public int nextTag() throws XMLStreamException { + return reader.nextTag(); + } + + public boolean hasNext() throws XMLStreamException { + return reader.hasNext(); + } + + public void close() throws XMLStreamException { + reader.close(); + } + + public String getNamespaceURI(String string) { + return reader.getNamespaceURI(string); + } + + public boolean isStartElement() { + return reader.isStartElement(); + } + + public boolean isEndElement() { + return reader.isEndElement(); + } + + public boolean isCharacters() { + return reader.isCharacters(); + } + + public boolean isWhiteSpace() { + return reader.isWhiteSpace(); + } + + public String getAttributeValue(String string, String string1) { + return reader.getAttributeValue(string, string1); + } + + public int getAttributeCount() { + return reader.getAttributeCount(); + } + + public QName getAttributeName(int i) { + return reader.getAttributeName(i); + } + + public String getAttributeNamespace(int i) { + return reader.getAttributeNamespace(i); + } + + public String getAttributeLocalName(int i) { + return reader.getAttributeLocalName(i); + } + + public String getAttributePrefix(int i) { + return reader.getAttributeLocalName(i); + } + + public String getAttributeType(int i) { + return reader.getAttributeType(i); + } + + public String getAttributeValue(int i) { + return reader.getAttributeValue(i); + } + + public boolean isAttributeSpecified(int i) { + return reader.isAttributeSpecified(i); + } + + public int getNamespaceCount() { + return reader.getNamespaceCount(); + } + + public String getNamespacePrefix(int i) { + return reader.getNamespacePrefix(i); + } + + public String getNamespaceURI(int i) { + return reader.getNamespaceURI(i); + } + + public NamespaceContext getNamespaceContext() { + return reader.getNamespaceContext(); + } + + public int getEventType() { + return reader.getEventType(); + } + + public String getText() { + return reader.getText(); + } + + public char[] getTextCharacters() { + return reader.getTextCharacters(); + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + return reader.getTextCharacters(i, chars, i1, i2); + } + + public int getTextStart() { + return reader.getTextStart(); + } + + public int getTextLength() { + return reader.getTextLength(); + } + + public String getEncoding() { + return reader.getEncoding(); + } + + public boolean hasText() { + return reader.hasText(); + } + + public Location getLocation() { + return reader.getLocation(); + } + + public QName getName() { + return reader.getName(); + } + + public String getLocalName() { + return reader.getLocalName(); + } + + public boolean hasName() { + return reader.hasName(); + } + + public String getNamespaceURI() { + return reader.getNamespaceURI(); + } + + public String getPrefix() { + return reader.getPrefix(); + } + + public String getVersion() { + return reader.getVersion(); + } + + public boolean isStandalone() { + return reader.isStandalone(); + } + + public boolean standaloneSet() { + return reader.standaloneSet(); + } + + public String getCharacterEncodingScheme() { + return reader.getCharacterEncodingScheme(); + } + + public String getPITarget() { + return reader.getPITarget(); + } + + public String getPIData() { + return reader.getPIData(); + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // nothing to do here + } + + public void init() { + // Nothing to do here + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java new file mode 100755 index 0000000000..c66d0fd934 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class Writer2ReaderDataPipe extends TransformerExtension implements DataPipe { + + private StringWriter writer = new StringWriter(); + + public Reader getResult() { + return new StringReader(writer.toString()); + } + + public Class getTargetType() { + return Reader.class; + } + + public int getWeight() { + return 50; + } + + public Writer getSink() { + return writer; + } + + public Class getSourceType() { + return Writer.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLDocumentStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLDocumentStreamReader.java new file mode 100644 index 0000000000..993516fa19 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLDocumentStreamReader.java @@ -0,0 +1,432 @@ +package org.apache.tuscany.core.databinding.xml; + +import java.util.NoSuchElementException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This class is derived from Apache Axis2 class + * org.apache.axis2.util.StreamWrapper. It's used wrap a XMLStreamReader to + * create a XMLStreamReader representing a document and it will produce + * START_DOCUMENT, END_DOCUMENT events. + */ +public class XMLDocumentStreamReader implements XMLStreamReader { + private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper + // will produce + // END_DOCUMENT + + private static final int STATE_COMPLETED = 3; // Done + + private static final int STATE_INIT = 0; // The wrapper will produce + // START_DOCUMENT + + private static final int STATE_SWITCHED = 1; // The real reader will + // produce events + + private XMLStreamReader realReader; + + private int state = STATE_INIT; + + public XMLDocumentStreamReader(XMLStreamReader realReader) { + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + this.realReader = realReader; + + if (realReader instanceof XMLFragmentStreamReader) { + ((XMLFragmentStreamReader)realReader).init(); + } + + // If the real reader is positioned at START_DOCUMENT, always use + // the real reader + if (realReader.getEventType() == START_DOCUMENT) { + state = STATE_SWITCHED; + } + } + + public void close() throws XMLStreamException { + realReader.close(); + } + + public int getAttributeCount() { + if (isDelegating()) { + return realReader.getAttributeCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (isDelegating()) { + return realReader.getAttributeLocalName(i); + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (isDelegating()) { + return realReader.getAttributeName(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (isDelegating()) { + return realReader.getAttributeNamespace(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (isDelegating()) { + return realReader.getAttributePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + if (isDelegating()) { + return realReader.getAttributeType(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(int i) { + if (isDelegating()) { + return realReader.getAttributeValue(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String s, String s1) { + if (isDelegating()) { + return realReader.getAttributeValue(s, s1); + } else { + throw new IllegalStateException(); + } + } + + public String getCharacterEncodingScheme() { + return realReader.getCharacterEncodingScheme(); + } + + public String getElementText() throws XMLStreamException { + if (isDelegating()) { + return realReader.getElementText(); + } else { + throw new XMLStreamException(); + } + } + + public String getEncoding() { + return realReader.getEncoding(); + } + + public int getEventType() { + int event = -1; + switch (state) { + case STATE_SWITCHED: + case STATE_COMPLETE_AT_NEXT: + event = realReader.getEventType(); + break; + case STATE_INIT: + event = START_DOCUMENT; + break; + case STATE_COMPLETED: + event = END_DOCUMENT; + break; + } + return event; + } + + public String getLocalName() { + if (isDelegating()) { + return realReader.getLocalName(); + } else { + throw new IllegalStateException(); + } + } + + public Location getLocation() { + if (isDelegating()) { + return realReader.getLocation(); + } else { + return null; + } + } + + public QName getName() { + if (isDelegating()) { + return realReader.getName(); + } else { + throw new IllegalStateException(); + } + } + + public NamespaceContext getNamespaceContext() { + return realReader.getNamespaceContext(); + } + + public int getNamespaceCount() { + if (isDelegating()) { + return realReader.getNamespaceCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespacePrefix(int i) { + if (isDelegating()) { + return realReader.getNamespacePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI() { + if (isDelegating()) { + return realReader.getNamespaceURI(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(int i) { + if (isDelegating()) { + return realReader.getNamespaceURI(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(String s) { + if (isDelegating()) { + return realReader.getNamespaceURI(s); + } else { + throw new IllegalStateException(); + } + } + + public String getPIData() { + if (isDelegating()) { + return realReader.getPIData(); + } else { + throw new IllegalStateException(); + } + } + + public String getPITarget() { + if (isDelegating()) { + return realReader.getPITarget(); + } else { + throw new IllegalStateException(); + } + } + + public String getPrefix() { + if (isDelegating()) { + return realReader.getPrefix(); + } else { + throw new IllegalStateException(); + } + } + + public Object getProperty(String s) throws IllegalArgumentException { + if (isDelegating()) { + return realReader.getProperty(s); + } else { + throw new IllegalArgumentException(); + } + } + + public String getText() { + if (isDelegating()) { + return realReader.getText(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (isDelegating()) { + return realReader.getTextCharacters(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (isDelegating()) { + return realReader.getTextCharacters(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (isDelegating()) { + return realReader.getTextLength(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (isDelegating()) { + return realReader.getTextStart(); + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + if (isDelegating()) { + return realReader.getVersion(); + } else { + return null; + } + } + + public boolean hasName() { + if (isDelegating()) { + return realReader.hasName(); + } else { + return false; + } + } + + public boolean hasNext() throws XMLStreamException { + if (state == STATE_COMPLETE_AT_NEXT) { + return true; + } else if (state == STATE_COMPLETED) { + return false; + } else if (state == STATE_SWITCHED) { + return realReader.hasNext(); + } else { + return true; + } + } + + public boolean hasText() { + if (isDelegating()) { + return realReader.hasText(); + } else { + return false; + } + } + + public boolean isAttributeSpecified(int i) { + if (isDelegating()) { + return realReader.isAttributeSpecified(i); + } else { + return false; + } + } + + public boolean isCharacters() { + if (isDelegating()) { + return realReader.isCharacters(); + } else { + return false; + } + } + + private boolean isDelegating() { + return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT; + } + + public boolean isEndElement() { + if (isDelegating()) { + return realReader.isEndElement(); + } else { + return false; + } + } + + public boolean isStandalone() { + if (isDelegating()) { + return realReader.isStandalone(); + } else { + return false; + } + } + + public boolean isStartElement() { + if (isDelegating()) { + return realReader.isStartElement(); + } else { + return false; + } + } + + public boolean isWhiteSpace() { + if (isDelegating()) { + return realReader.isWhiteSpace(); + } else { + return false; + } + } + + public int next() throws XMLStreamException { + int returnEvent; + + switch (state) { + case STATE_SWITCHED: + returnEvent = realReader.next(); + if (returnEvent == END_DOCUMENT) { + state = STATE_COMPLETED; + } else if (!realReader.hasNext()) { + state = STATE_COMPLETE_AT_NEXT; + } + break; + case STATE_INIT: + state = STATE_SWITCHED; + returnEvent = realReader.getEventType(); + break; + case STATE_COMPLETE_AT_NEXT: + state = STATE_COMPLETED; + returnEvent = END_DOCUMENT; + break; + case STATE_COMPLETED: + // oops - no way we can go beyond this + throw new NoSuchElementException("End of stream has reached."); + default: + throw new UnsupportedOperationException(); + } + + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + if (isDelegating()) { + return realReader.nextTag(); + } else { + throw new XMLStreamException(); + } + } + + public void require(int i, String s, String s1) throws XMLStreamException { + if (isDelegating()) { + realReader.require(i, s, s1); + } + } + + public boolean standaloneSet() { + if (isDelegating()) { + return realReader.standaloneSet(); + } else { + return false; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReader.java new file mode 100644 index 0000000000..f54a43bb29 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReader.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +public interface XMLFragmentStreamReader extends XMLStreamReader { + QName NIL_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi"); + String NIL_VALUE_TRUE = "true"; + + /** + * this will help to handle Text within the current element. user should + * pass the element text to the property list as this ELEMENT_TEXT as the + * key. This key deliberately has a space in it so that it is not a valid + * XML name + */ + String ELEMENT_TEXT = "Element Text"; + + /** + * Extra method to query the state of the pullparser + */ + boolean isDone(); + + /** + * add the parent namespace context to this parser + */ + void setParentNamespaceContext(NamespaceContext nsContext); + + /** + * Initiate the parser - this will do whatever the needed tasks to initiate + * the parser and must be called before attempting any specific parsing + * using this parser + */ + void init(); +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java new file mode 100644 index 0000000000..fe67225f81 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java @@ -0,0 +1,857 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This is the new implementation of the XMLFramentStreamReader. The approach + * here is simple When the pull parser needs to generate events for a particular + * name-value(s) pair it always handes over (delegates) the task to another pull + * parser which knows how to deal with it The common types of name value pairs + * we'll come across are + *

        + *
      • String name/QName name - String value + *
      • String name/QName name - String[] value + *
      • QName name/String name - XMLStreamReader value + *
      • QName name/String name - XMLStreamable value + *
      • QName name/String name - Java bean + *
      • QName name/String name - Datahandler + * + *
      + *

      As for the attributes, these are the possible combinations in the array + *

        + *
      • String name/QName name - String value + *
      + * Note that certain array methods have been deliberately removed to avoid + * complications. The generated code will take the trouble to lay the elements + * of the array in the correct order

      Hence there will be a parser impl + * that knows how to handle these types, and this parent parser will always + * delegate these tasks to the child pullparasers in effect this is one huge + * state machine that has only a few states and delegates things down to the + * child parsers whenever possible

      + * + * @version $Rev$ $Date$ + */ +public class XMLFragmentStreamReaderImpl implements XMLFragmentStreamReader { + + private static final int DELEGATED_STATE = 2; + private static final int END_ELEMENT_STATE = 1; + // states for this pullparser - it can only have four states + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 3; + + protected NamedProperty[] attributes; + + // reference to the child reader + protected XMLFragmentStreamReader childReader; + // current property index + // initialized at zero + protected int index; + protected Map declaredNamespaceMap = new HashMap(); + protected QName elementQName; + + // we always create a new namespace context + protected DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + + protected NamedProperty[] elements; + + // integer field that keeps the state of this + // parser. + protected int state = START_ELEMENT_STATE; + + /* + * we need to pass in a namespace context since when delegated, we've no + * idea of the current namespace context. So it needs to be passed on here! + */ + public XMLFragmentStreamReaderImpl(QName elementQName, NamedProperty[] elements, NamedProperty[] attributes) { + // validate the lengths, since both the arrays are supposed + // to have + this.elements = elements == null ? new NamedProperty[0] : elements; + this.elementQName = elementQName; + this.attributes = attributes == null ? new NamedProperty[0] : attributes; + } + + protected XMLFragmentStreamReaderImpl(QName elementQName) { + this.elementQName = elementQName; + } + + /** + * add the namespace context + */ + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // register the namespace context passed in to this + this.namespaceContext.setParentNsContext(nsContext); + + } + + protected NamedProperty[] getElements() { + return elements; + } + + protected NamedProperty[] getAttributes() { + return attributes; + } + + protected QName[] getNamespaces() { + return new QName[0]; + } + + /** + * @param prefix + * @param uri + */ + protected void addToNsMap(String prefix, String uri) { + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + namespaceContext.pushNamespace(prefix, uri); + declaredNamespaceMap.put(prefix, uri); + } + } + + public void close() throws XMLStreamException { + // do nothing here - we have no resources to free + } + + public int getAttributeCount() { + return (state == DELEGATED_STATE) ? childReader.getAttributeCount() : (state == START_ELEMENT_STATE + ? getAttributes().length : 0); + } + + public String getAttributeLocalName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeLocalName(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getLocalPart(); + } + } else { + throw new IllegalStateException(); + } + } + + /** + * @param i + */ + public QName getAttributeName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeName(i); + } else if (state == START_ELEMENT_STATE) { + if ((i >= (getAttributes().length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + QName attribPointer = getAttributes()[i].getKey(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer == null) { + throw new UnsupportedOperationException(); + } else if (attribPointer instanceof QName) { + return (QName)attribPointer; + } else { + return null; + } + } + } else { + throw new IllegalStateException(); // as per the api contract + } + + } + + public String getAttributeNamespace(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeNamespace(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getNamespaceURI(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributePrefix(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getPrefix(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not supported + } + + public String getAttributeValue(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeValue(i); + } else if (state == START_ELEMENT_STATE) { + if ((i >= (getAttributes().length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + QName attribPointer = getAttributes()[i].getKey(); + Object omAttribObj = getAttributes()[i].getValue(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer == null) { + throw new UnsupportedOperationException(); + } else if (attribPointer instanceof QName) { + return (String)omAttribObj; + } else { + return null; + } + } + } else { + throw new IllegalStateException(); + } + + } + + public String getAttributeValue(String nsUri, String localName) { + + int attribCount = getAttributeCount(); + String returnValue = null; + QName attribQualifiedName; + for (int i = 0; i < attribCount; i++) { + attribQualifiedName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attribQualifiedName.getLocalPart())) { + returnValue = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attribQualifiedName.getLocalPart()) && nsUri.equals(attribQualifiedName + .getNamespaceURI())) { + returnValue = getAttributeValue(i); + break; + } + } + + } + + return returnValue; + } + + public String getCharacterEncodingScheme() { + return null; // todo - should we return something for this ? + } + + /** + * todo implement the right contract for this + * + * @throws XMLStreamException + */ + public String getElementText() throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getElementText(); + } else { + return null; + } + + } + + // ///////////////////////////////////////////////////////////////////////// + // / attribute handling + // ///////////////////////////////////////////////////////////////////////// + + public String getEncoding() { + if (state == DELEGATED_STATE) { + return childReader.getEncoding(); + } else { + // we've no idea what the encoding is going to be in this case + // perhaps we ought to return some constant here, which the user + // might + // have access to change! + return null; + } + } + + public int getEventType() { + if (state == START_ELEMENT_STATE) { + return START_ELEMENT; + } else if (state == END_ELEMENT_STATE) { + return END_ELEMENT; + } else if (state == TEXT_STATE) { + return CHARACTERS; + } else { // this is the delegated state + return childReader.getEventType(); + } + } + + public String getLocalName() { + if (state == DELEGATED_STATE) { + return childReader.getLocalName(); + } else if (state != TEXT_STATE) { + return elementQName.getLocalPart(); + } else { + throw new IllegalStateException(); + } + } + + /** + */ + public Location getLocation() { + // return a default location + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state == DELEGATED_STATE) { + return childReader.getName(); + } else if (state != TEXT_STATE) { + return elementQName; + } else { + throw new IllegalStateException(); + } + + } + + public NamespaceContext getNamespaceContext() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceContext(); + } else { + return namespaceContext; + } + + } + + public int getNamespaceCount() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceCount(); + } else { + return declaredNamespaceMap.size(); + } + } + + /** + * @param i + */ + public String getNamespacePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespacePrefix(i); + } else if (state != TEXT_STATE) { + // order the prefixes + String[] prefixes = makePrefixArray(); + if ((i >= prefixes.length) || (i < 0)) { + return null; + } else { + return prefixes[i]; + } + + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getNamespaceURI(); + } + } + + // ///////////////////////////////////////////////////////////////////////// + // //////////// end of attribute handling + // ///////////////////////////////////////////////////////////////////////// + + // ////////////////////////////////////////////////////////////////////////// + // //////////// namespace handling + // ////////////////////////////////////////////////////////////////////////// + + public String getNamespaceURI(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(i); + } else if (state != TEXT_STATE) { + String namespacePrefix = getNamespacePrefix(i); + return namespacePrefix == null ? null : (String)declaredNamespaceMap.get(namespacePrefix); + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public String getPIData() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPITarget() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPrefix() { + if (state == DELEGATED_STATE) { + return childReader.getPrefix(); + } else if (state == TEXT_STATE) { + return null; + } else { + String prefix = elementQName.getPrefix(); + return "".equals(prefix) ? null : prefix; + } + } + + // ///////////////////////////////////////////////////////////////////////// + // /////// end of namespace handling + // ///////////////////////////////////////////////////////////////////////// + + /** + * @param key + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return null; + } else if (state == TEXT_STATE) { + return null; + } else if (state == DELEGATED_STATE) { + return childReader.getProperty(key); + } else { + return null; + } + + } + + public String getText() { + if (state == DELEGATED_STATE) { + return childReader.getText(); + } else if (state == TEXT_STATE) { + return (String)getElements()[index - 1].getValue(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(); + } else if (state == TEXT_STATE) { + return getElements()[index - 1].getValue() == null ? new char[0] : ((String)getElements()[index - 1] + .getValue()).toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + private int copy(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextCharacters(); + if (sourceStart > source.length) { + throw new IndexOutOfBoundsException("source start > source length"); + } + int sourceLen = source.length - sourceStart; + if (length > sourceLen) { + length = sourceLen; + } + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(i, chars, i1, i2); + } else if (state == TEXT_STATE) { + return copy(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == DELEGATED_STATE) { + return childReader.getTextLength(); + } else if (state == TEXT_STATE) { + return getTextCharacters().length; + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (state == DELEGATED_STATE) { + return childReader.getTextStart(); + } else if (state == TEXT_STATE) { + return 0; // assume text always starts at 0 + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + return null; + } + + public boolean hasName() { + // since this parser always has a name, the hasname + // has to return true if we are still navigating this element + // if not we should ask the child reader for it. + if (state == DELEGATED_STATE) { + return childReader.hasName(); + } else { + return state != TEXT_STATE; + } + } + + /** + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + if (state == DELEGATED_STATE) { + if (childReader.isDone()) { + // the child reader is done. We shouldn't be getting the + // hasnext result from the child pullparser then + return true; + } else { + return childReader.hasNext(); + } + } else { + return state == START_ELEMENT_STATE || state == TEXT_STATE; + + } + } + + /** + * check the validity of this implementation + */ + public boolean hasText() { + if (state == DELEGATED_STATE) { + return childReader.hasText(); + } else { + return state == TEXT_STATE; + } + + } + + /** + * we need to split out the calling to the populate namespaces seperately + * since this needs to be done *after* setting the parent namespace context. + * We cannot assume it will happen at construction! + */ + public void init() { + // here we have an extra issue to attend to. we need to look at the + // prefixes and uris (the combination) and populate a hashmap of + // namespaces. The hashmap of namespaces will be used to serve the + // namespace context + + populateNamespaceContext(); + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public boolean isCharacters() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isCharacters(); + } + + /** + * are we done ? + */ + public boolean isDone() { + return state == END_ELEMENT_STATE; + } + + public boolean isEndElement() { + if (state == START_ELEMENT_STATE) { + return false; + } else if (state == END_ELEMENT_STATE) { + return true; + } + return childReader.isEndElement(); + } + + public boolean isStandalone() { + return true; + } + + public boolean isStartElement() { + if (state == START_ELEMENT_STATE) { + return true; + } else if (state == END_ELEMENT_STATE) { + return false; + } + return childReader.isStartElement(); + } + + public boolean isWhiteSpace() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isWhiteSpace(); + } + + /** + * Get the prefix list from the hastable and take that into an array + */ + private String[] makePrefixArray() { + String[] prefixes = (String[])declaredNamespaceMap.keySet().toArray(new String[declaredNamespaceMap.size()]); + Arrays.sort(prefixes); + return prefixes; + } + + /** + * By far this should be the most important method in this class this method + * changes the state of the parser + */ + public int next() throws XMLStreamException { + int returnEvent = -1; // invalid state is the default state + switch (state) { + case START_ELEMENT_STATE: + // current element is start element. We should be looking at the + // property list and making a pullparser for the property value + if (getElements() == null || getElements().length == 0) { + // no properties - move to the end element state + // straightaway + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + // there are properties. now we should delegate this task to + // a + // child reader depending on the property type + returnEvent = processProperties(); + + } + break; + case END_ELEMENT_STATE: + // we've reached the end element already. If the user tries to + // push + // further ahead then it is an exception + throw new XMLStreamException("Trying to go beyond the end of the pullparser"); + + case DELEGATED_STATE: + if (childReader.isDone()) { + // we've reached the end! + if (index > (getElements().length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + } else { + returnEvent = childReader.next(); + } + break; + + case TEXT_STATE: + // if there are any more event we should be delegating to + // processProperties. if not we just return an end element + if (index > (getElements().length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + break; + } + return returnEvent; + } + + // ///////////////////////////////////////////////////////////////////////// + // / Other utility methods + // //////////////////////////////////////////////////////////////////////// + + /** + * todo implement this + * + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + return 0; + } + + /** + * Populates a namespace context + */ + private void populateNamespaceContext() { + + // first add the current element namespace to the namespace context + // declare it if not found + addToNsMap(elementQName.getPrefix(), elementQName.getNamespaceURI()); + + for (QName n : getNamespaces()) { + addToNsMap(n.getPrefix(), n.getNamespaceURI()); + } + + // traverse through the attributes and populate the namespace context + // the attrib list can be of many combinations + // the valid combinations are + // String - String + // QName - QName + // null - OMAttribute + + for (int i = 0; i < getAttributes().length; i++) { // jump in two + QName attrQName = getAttributes()[i].getKey(); + if (!"".equals(attrQName.getNamespaceURI())) { + addToNsMap(attrQName.getPrefix(), attrQName.getNamespaceURI()); + } + } + } + + /** + * A convenient method to reuse the properties + * + * @return event to be thrown + * @throws XMLStreamException + */ + private int processProperties() throws XMLStreamException { + // move to the next property depending on the current property + // index + QName propertyQName = getElements()[index].getKey(); + boolean textFound = false; + if (propertyQName == null) { + throw new XMLStreamException("property key cannot be null!"); + } else if (ELEMENT_TEXT.equals(propertyQName.getLocalPart())) { + // propPointer being a String has a special case + // that is it can be a the special constant ELEMENT_TEXT that + // says this text event + textFound = true; + } + + // ok! we got the key. Now look at the value + Object propertyValue = getElements()[index].getValue(); + // cater for the special case now + if (textFound) { + // no delegation here - make the parser null and immediately + // return with the event characters + childReader = null; + state = TEXT_STATE; + ++index; + return CHARACTERS; + } else if (propertyValue == null) { + // if the value is null we delegate the work to a nullable + // parser + childReader = new NilElementStreamReader(propertyQName); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof String) { + // strings are handled by the NameValuePairStreamReader + childReader = new NameValuePairStreamReader(propertyQName, (String)propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof String[]) { + // string[] are handled by the NameValueArrayStreamReader + // if the array is empty - skip it + if (((String[])propertyValue).length == 0) { + // advance the index + ++index; + return processProperties(); + } else { + childReader = new NameValueArrayStreamReader(propertyQName, (String[])propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } + + } else if (propertyValue instanceof XMLStreamable) { + // ADBbean has it's own method to get a reader + XMLStreamReader reader = ((XMLStreamable)propertyValue).getXMLStreamReader(propertyQName); + // we know for sure that this is an ADB XMLStreamreader. + // However we need to make sure that it is compatible + if (reader instanceof XMLFragmentStreamReader) { + childReader = (XMLFragmentStreamReader)reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // wrap it to make compatible + childReader = new WrappingXMLStreamReader(reader); + } + } else if (propertyValue instanceof XMLStreamReader) { + XMLStreamReader reader = (XMLStreamReader)propertyValue; + if (reader instanceof XMLFragmentStreamReader) { + childReader = (XMLFragmentStreamReader)reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // wrap it to make compatible + childReader = new WrappingXMLStreamReader(reader); + } + + } else { + // all special possiblilities has been tried! Let's treat + // the thing as a bean and try generating events from it + childReader = new WrappingXMLStreamReader(BeanUtil.getXMLStreamReader(propertyValue, propertyQName)); + // we cannot register the namespace context here + } + + // set the state here + state = DELEGATED_STATE; + // we are done with the delegation + // increment the property index + ++index; + return childReader.getEventType(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + public boolean standaloneSet() { + return true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLGroupDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLGroupDataBinding.java new file mode 100644 index 0000000000..d206ff8b2c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLGroupDataBinding.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.lang.annotation.Annotation; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Result; +import javax.xml.transform.Source; + +import org.apache.tuscany.core.databinding.impl.GroupDataBinding; +import org.apache.tuscany.spi.idl.XMLType; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * A Group DataBinding + * + * @version $Rev$ $Date$ + */ +public class XMLGroupDataBinding extends GroupDataBinding { + + public XMLGroupDataBinding() { + super(new Class[] {InputStream.class, OutputStream.class, Reader.class, Writer.class, Source.class, + Result.class, InputSource.class, ContentHandler.class, XMLStreamReader.class, + XMLStreamWriter.class, XMLEventReader.class, XMLEventWriter.class}); + } + + @Override + protected Object getLogical(Class markerType, Annotation[] annotations) { + return XMLType.UNKNOWN; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java new file mode 100644 index 0000000000..6ecaa85be4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML XMLStreamReader + */ +@Service(Transformer.class) +public class XMLStreamReader2Node extends TransformerExtension implements + PullTransformer { + private SAX2DOMPipe pipe = new SAX2DOMPipe(); + + private XMLStreamReader2SAX stax2sax = new XMLStreamReader2SAX(); + + public Node transform(XMLStreamReader source, TransformationContext context) { + try { + stax2sax.transform(source, pipe.getSink(), context); + return pipe.getResult(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return XMLStreamReader.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java new file mode 100644 index 0000000000..0c6f0b8df7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; + +/** + * XMLStreamReader to SAX events + */ +@Service(Transformer.class) +public class XMLStreamReader2SAX extends TransformerExtension implements + PushTransformer { + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#getSourceType() + */ + public Class getTargetType() { + return ContentHandler.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#getSourceType() + */ + public Class getSourceType() { + return XMLStreamReader.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#getWeight() + */ + public int getWeight() { + return 20; + } + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#transform(java.lang.Object, + * java.lang.Object, + * org.apache.tuscany.spi.databinding.TransformationContext) + */ + public void transform(XMLStreamReader source, ContentHandler sink, TransformationContext context) { + StAX2SAXAdapter adapter = new StAX2SAXAdapter(false); + try { + adapter.parse(source, sink); + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java new file mode 100755 index 0000000000..85ac7b5af6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class XMLStreamReader2String extends TransformerExtension implements + PullTransformer { + + public String transform(XMLStreamReader source, TransformationContext context) { + try { + return StAXHelper.save(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return XMLStreamReader.class; + } + + public Class getTargetType() { + return String.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java new file mode 100644 index 0000000000..8b44f526d0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java @@ -0,0 +1,266 @@ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +/** + * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps into the XMLStreamWriter + */ +public class XMLStreamSerializer implements XMLStreamConstants { + public static final String NAMESPACE_PREFIX = "ns"; + private static int namespaceSuffix; + + /* + * The behavior of the serializer is such that it returns when it encounters the starting element for the second + * time. The depth variable tracks the depth of the serilizer and tells it when to return. Note that it is assumed + * that this serialization starts on an Element. + */ + + /** + * Field depth + */ + private int depth; + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @param nsCtxt + * @return string + */ + private String generateUniquePrefix(NamespaceContext nsCtxt) { + String prefix = NAMESPACE_PREFIX + namespaceSuffix++; + // null should be returned if the prefix is not bound! + while (nsCtxt.getNamespaceURI(prefix) != null) { + prefix = NAMESPACE_PREFIX + namespaceSuffix++; + } + + return prefix; + } + + /** + * Method serialize. + * + * @param node + * @param writer + * @throws XMLStreamException + */ + public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException { + serializeNode(node, writer); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + int count = reader.getAttributeCount(); + String prefix; + String namespaceName; + String writerPrefix; + for (int i = 0; i < count; i++) { + prefix = reader.getAttributePrefix(i); + namespaceName = reader.getAttributeNamespace(i); + /* + * Due to parser implementations returning null as the namespace URI (for the empty namespace) we need to + * make sure that we deal with a namespace name that is not null. The best way to work around this issue is + * to set the namespace uri to "" if it is null + */ + if (namespaceName == null) { + namespaceName = ""; + } + + writerPrefix = writer.getNamespaceContext().getPrefix(namespaceName); + + if (!"".equals(namespaceName)) { + // prefix has already being declared but this particular + // attrib has a + // no prefix attached. So use the prefix provided by the + // writer + if (writerPrefix != null && (prefix == null || prefix.equals(""))) { + writer.writeAttribute(writerPrefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // writer prefix is available but different from the + // current + // prefix of the attrib. We should be decalring the new + // prefix + // as a namespace declaration + } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) { + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // prefix is null (or empty), but the namespace name is + // valid! it has not + // being written previously also. So we need to generate + // a prefix + // here + } else if (prefix == null || prefix.equals("")) { + prefix = generateUniquePrefix(writer.getNamespaceContext()); + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } else { + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } + } else { + // empty namespace is equal to no namespace! + writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i)); + } + + } + } + + /** + * Method serializeCData. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCData(reader.getText()); + } + + /** + * Method serializeComment. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeComment(reader.getText()); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + String prefix = reader.getPrefix(); + String nameSpaceName = reader.getNamespaceURI(); + if (nameSpaceName != null) { + String writerPrefix = writer.getPrefix(nameSpaceName); + if (writerPrefix != null) { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + } else { + if (prefix != null) { + writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName); + writer.writeNamespace(prefix, nameSpaceName); + writer.setPrefix(prefix, nameSpaceName); + } else { + // [rfeng] We need to set default NS 1st before calling writeStateElement + writer.setDefaultNamespace(nameSpaceName); + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + writer.writeDefaultNamespace(nameSpaceName); + } + } + } else { + writer.writeStartElement(reader.getLocalName()); + } + + // add the namespaces + int count = reader.getNamespaceCount(); + String namespacePrefix; + for (int i = 0; i < count; i++) { + namespacePrefix = reader.getNamespacePrefix(i); + // [rfeng] The following is commented out to allow to default ns + // if (namespacePrefix != null && namespacePrefix.length() == 0) { + // continue; + // } + + serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer); + } + + // add attributes + serializeAttributes(reader, writer); + + } + + /** + * Method serializeEndElement. + * + * @param writer + * @throws XMLStreamException + */ + protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * Method serializeNamespace. + * + * @param prefix + * @param uri + * @param writer + * @throws XMLStreamException + */ + private void serializeNamespace(String prefix, String uri, XMLStreamWriter writer) throws XMLStreamException { + String prefix1 = writer.getPrefix(uri); + if (prefix1 == null) { + writer.writeNamespace(prefix, uri); + writer.setPrefix(prefix, uri); + } + } + + /** + * Method serializeNode. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + while (true) { + int event = reader.getEventType(); + if (event == START_ELEMENT) { + serializeElement(reader, writer); + depth++; + } else if (event == ATTRIBUTE) { + serializeAttributes(reader, writer); + } else if (event == CHARACTERS) { + serializeText(reader, writer); + } else if (event == COMMENT) { + serializeComment(reader, writer); + } else if (event == CDATA) { + serializeCData(reader, writer); + } else if (event == END_ELEMENT) { + serializeEndElement(writer); + depth--; + } else if (event == START_DOCUMENT) { + depth++; // if a start document is found then increment + writer.writeStartDocument(); + // the depth + } else if (event == END_DOCUMENT) { + if (depth != 0) { + depth--; // for the end document - reduce the depth + } + writer.writeEndDocument(); + } + if (depth == 0) { + break; + } + if (reader.hasNext()) { + reader.next(); + } else { + break; + } + } + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCharacters(reader.getText()); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java new file mode 100644 index 0000000000..285e5cdf60 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +/** + * An interface represents data that can be read using StAX streaming + * + * @version $Rev$ $Date$ + */ +public interface XMLStreamable { + /** + * Get the XMLStreamReader for StAX processing + * + * @param rootElementName the name of the element to be generated + * @return Returns a pull parser. + */ + XMLStreamReader getXMLStreamReader(QName rootElementName); +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java new file mode 100644 index 0000000000..4d8925c3b5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.lang.annotation.Annotation; + +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.DataType; + +/** + * A DataBinding for the XML string + * + * @version $Rev$ $Date$ + */ +public class XMLStringDataBinding extends DataBindingExtension { + public static final String NAME = String.class.getName(); + public static final String[] ALIASES = new String[] {"xml.string"}; + + public XMLStringDataBinding() { + super(NAME, ALIASES, String.class); + } + + @Override + public boolean introspect(DataType type, Annotation[] annotations) { + if (registry.getDataBinding(type.getDataBinding()) == this) { + type.setDataBinding(getName()); + type.setLogical(XMLType.UNKNOWN); + return true; + } else { + return false; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java new file mode 100644 index 0000000000..c931cccde9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * Base class for DeploymentContext implementations. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractDeploymentContext implements DeploymentContext { + private final ClassLoader classLoader; + private final URL scdlLocation; + private final Map properties = new HashMap(); + + protected AbstractDeploymentContext(ClassLoader classLoader, URL scdlLocation) { + this.classLoader = classLoader; + this.scdlLocation = scdlLocation; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public URL getScdlLocation() { + return scdlLocation; + } + + public Object getExtension(String name) { + return properties.get(name); + } + + public void putExtension(String name, Object value) { + if (value == null) { + properties.remove(name); + } else { + properties.put(name, value); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java new file mode 100644 index 0000000000..c489ba04c3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * An holder that can be used during the load process to store information that is not part of the logical assembly + * model. This should be regarded as transient and references to this context should not be stored inside the model. + * + * @version $Rev$ $Date$ + */ +public class ChildDeploymentContext extends AbstractDeploymentContext { + private final DeploymentContext parent; + + /** + * Constructor specifying the loader for application resources. + * + * @param parent the parent of this context + * @param classLoader the loader for application resources + * @param scdlLocation the location of the SCDL being deployed + */ + public ChildDeploymentContext(DeploymentContext parent, ClassLoader classLoader, URL scdlLocation) { + super(classLoader, scdlLocation); + assert parent != null; + this.parent = parent; + } + + public DeploymentContext getParent() { + return parent; + } + + public XMLInputFactory getXmlFactory() { + return parent.getXmlFactory(); + } + + public ScopeContainer getCompositeScope() { + return parent.getCompositeScope(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java new file mode 100644 index 0000000000..ce5858ae1c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.Builder; +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.builder.BuilderInstantiationException; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.ComponentRegistrationException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.PrepareException; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeContainerMonitor; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.event.RuntimeEventListener; +import org.apache.tuscany.spi.loader.Loader; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.Implementation; + +import org.apache.tuscany.api.annotation.Monitor; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.component.scope.CompositeScopeContainer; + +/** + * Default implementation of Deployer. + * + * @version $Rev$ $Date$ + */ +public class DeployerImpl implements Deployer { + private Loader loader; + protected XMLInputFactory xmlFactory; + protected Builder builder; + protected ScopeContainerMonitor monitor; + + public DeployerImpl(XMLInputFactory xmlFactory, Loader loader, Builder builder) { + this.xmlFactory = xmlFactory; + this.loader = loader; + this.builder = builder; + } + + public DeployerImpl() { + xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + } + + @Autowire + public void setLoader(LoaderRegistry loader) { + this.loader = loader; + } + + @Autowire + public void setBuilder(BuilderRegistry builder) { + this.builder = builder; + } + + @Monitor + public void setMonitor(ScopeContainerMonitor monitor) { + this.monitor = monitor; + } + + public > Component deploy(CompositeComponent parent, + ComponentDefinition componentDefinition) + throws LoaderException, BuilderException, PrepareException { + final ScopeContainer scopeContainer = new CompositeScopeContainer(monitor); + scopeContainer.start(); + DeploymentContext deploymentContext = new RootDeploymentContext(null, xmlFactory, scopeContainer, null); + try { + load(parent, componentDefinition, deploymentContext); + } catch (LoaderException e) { + e.addContextName(componentDefinition.getName()); + throw e; + } + Component component = (Component) build(parent, componentDefinition, deploymentContext); + // create a listener so the scope container is shutdown when the top-level composite stops + RuntimeEventListener listener = new RuntimeEventListener() { + public void onEvent(Event event) { + scopeContainer.onEvent(event); + if (event instanceof CompositeStop) { + scopeContainer.stop(); + } + } + }; + component.addListener(listener); + component.prepare(); + try { + parent.register(component); + } catch (ComponentRegistrationException e) { + throw new BuilderInstantiationException("Error registering component", e); + } + return component; + } + + public > Component deployFromContribution(CompositeComponent parent, + ComponentDefinition componentDefinition) throws BuilderException, PrepareException { + final ScopeContainer scopeContainer = new CompositeScopeContainer(monitor); + scopeContainer.start(); + DeploymentContext deploymentContext = new RootDeploymentContext(null, xmlFactory, scopeContainer, null); +// try { +// load(parent, componentDefinition, deploymentContext); +// } catch (LoaderException e) { +// e.addContextName(componentDefinition.getName()); +// throw e; +// } + Component component = (Component) build(parent, componentDefinition, deploymentContext); + // create a listener so the scope container is shutdown when the top-level composite stops + RuntimeEventListener listener = new RuntimeEventListener() { + public void onEvent(Event event) { + scopeContainer.onEvent(event); + if (event instanceof CompositeStop) { + scopeContainer.stop(); + } + } + }; + component.addListener(listener); + component.prepare(); + try { + parent.register(component); + } catch (ComponentRegistrationException e) { + throw new BuilderInstantiationException("Error registering component", e); + } + return component; + } + + /** + * Load the componentDefinition type information for the componentDefinition being deployed. For a typical + * deployment this will result in the SCDL definition being loaded. + * + * @param componentDefinition the componentDefinition being deployed + * @param deploymentContext the current deployment context + */ + protected > void load(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext deploymentContext) throws LoaderException { + loader.loadComponentType(parent, componentDefinition.getImplementation(), deploymentContext); + } + + /** + * Build the runtime context for a loaded componentDefinition. + * + * @param parent the context that will be the parent of the new sub-context + * @param componentDefinition the componentDefinition being deployed + * @param deploymentContext the current deployment context + * @return the new runtime context + */ + protected > SCAObject build(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext deploymentContext) + throws BuilderException { + return builder.build(parent, componentDefinition, deploymentContext); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java new file mode 100644 index 0000000000..be5cc56d51 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * A holder that can be used during the load process to store information that is not part of the logical assembly + * model. This should be regarded as transient and references to this context should not be stored inside the model. + * + * @version $Rev$ $Date$ + */ +public class RootDeploymentContext extends AbstractDeploymentContext { + private final XMLInputFactory xmlFactory; + private final ScopeContainer scopeContainer; + + /** + * Constructor specifying the loader for application resources. + * + * @param classLoader the loader for application resources + * @param xmlFactory a factory that can be used to obtain an StAX XMLStreamReader + * @param scopeContainer the scope context representing this deployment's COMPOSITE scope + * @param scdlLocation the location of the SCDL being deployed + */ + public RootDeploymentContext(ClassLoader classLoader, + XMLInputFactory xmlFactory, + ScopeContainer scopeContainer, + URL scdlLocation) { + super(classLoader, scdlLocation); + this.xmlFactory = xmlFactory; + this.scopeContainer = scopeContainer; + } + + public DeploymentContext getParent() { + return null; + } + + public XMLInputFactory getXmlFactory() { + return xmlFactory; + } + + public ScopeContainer getCompositeScope() { + return scopeContainer; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java new file mode 100644 index 0000000000..934510df27 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/federation/FederatedDeployer.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer.federation; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.component.scope.CompositeScopeContainer; +import org.apache.tuscany.core.deployer.DeployerImpl; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.PrepareException; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.marshaller.MarshalException; +import org.apache.tuscany.spi.marshaller.ModelMarshaller; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.services.discovery.DiscoveryService; +import org.apache.tuscany.spi.services.discovery.RequestListener; + +/** + * Federated deployer that deploys components in response to asynchronous + * messages from the federated domain. + * + * @version $Revision$ $Date$ + * + */ +public class FederatedDeployer extends DeployerImpl implements RequestListener { + + /** QName of the message. */ + private static final QName MESSAGE_TYPE = new QName("http://www.osoa.org/xmlns/sca/1.0", "composite"); + + /** Marshaller. */ + private ModelMarshaller> marshaller; + + /** + * Deploys the component. + * @param content SCDL content. + * @return Response to the request message. + * + * TODO Handle response messages. + */ + public XMLStreamReader onRequest(XMLStreamReader content) { + + // TODO get this from somewhere + final CompositeComponent parent = null; + + final ScopeContainer scopeContainer = new CompositeScopeContainer(monitor); + scopeContainer.start(); + + final DeploymentContext deploymentContext = new RootDeploymentContext(null, xmlFactory, scopeContainer, null); + + try { + + final ComponentDefinition definition = marshaller.unmarshall(content, false); + final Component component = (Component) builder.build(parent, definition, deploymentContext); + + component.prepare(); + component.start(); + + } catch (MarshalException ex) { + return null; + } catch (BuilderException ex) { + return null; + } catch (PrepareException ex) { + return null; + } + + return null; + } + + /** + * Injects the discovery service. + * @param discoveryService Discovery service to be injected. + */ + @Autowire + public void setDiscoveryService(DiscoveryService discoveryService) { + discoveryService.registerRequestListener(MESSAGE_TYPE, this); + } + + /** + * Injects the model marshaller. + * @param marshaller Marshaller. + */ + @Autowire + public void setMarshaller(ModelMarshaller> marshaller) { + this.marshaller = marshaller; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java new file mode 100644 index 0000000000..f52bd4cfb1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.idl.java; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; + +/** + * Denotes an illegal callback interface + * + * @version $Rev$ $Date$ + */ + +public class IllegalCallbackException extends InvalidServiceContractException { + + public IllegalCallbackException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java new file mode 100644 index 0000000000..5ca25bb0e1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.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.core.idl.java; + +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.util.stax.StaxUtil; + +/** + * Loads a Java interface definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class InterfaceJavaLoader extends LoaderExtension { + public static final QName INTERFACE_JAVA = new QName(SCA_NS, "interface.java"); + + private final JavaInterfaceProcessorRegistry interfaceRegsitry; + + @Constructor({"registry", "interfaceRegsitry"}) + public InterfaceJavaLoader(@Autowire LoaderRegistry registry, + @Autowire JavaInterfaceProcessorRegistry interfaceRegistry) { + super(registry); + this.interfaceRegsitry = interfaceRegistry; + } + + public QName getXMLType() { + return INTERFACE_JAVA; + } + + public JavaServiceContract load(CompositeComponent parent, + ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + assert INTERFACE_JAVA.equals(reader.getName()); + InteractionScope interactionScope = StaxUtil.interactionScope(reader.getAttributeValue(null, "scope")); + String name = reader.getAttributeValue(null, "interface"); + if (name == null) { + // allow "class" as well as seems to be a common mistake + name = reader.getAttributeValue(null, "class"); + } + if (name == null) { + throw new InvalidValueException("interface name not supplied"); + } + Class interfaceClass = LoaderUtil.loadClass(name, deploymentContext.getClassLoader()); + + name = reader.getAttributeValue(null, "callbackInterface"); + Class callbackClass = (name != null) ? LoaderUtil.loadClass(name, deploymentContext.getClassLoader()) : null; + + Map, ModelObject> extensions = new HashMap, ModelObject>(); + while (true) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + ModelObject mo = registry.load(parent, null, reader, deploymentContext); + if (mo != null) { + extensions.put(mo.getClass(), mo); + } + } else if (event == XMLStreamConstants.END_ELEMENT && reader.getName().equals(INTERFACE_JAVA)) { + break; + } + } + JavaServiceContract serviceContract; + try { + serviceContract = interfaceRegsitry.introspect(interfaceClass, callbackClass, false); + } catch (InvalidServiceContractException e) { + throw new LoaderException(interfaceClass.getName(), e); + } + + // Set databinding from the SCDL extension + DataType dataType = (DataType) extensions.get(DataType.class); + if (dataType != null) { + serviceContract.setDataBinding(dataType.getDataBinding()); + } + serviceContract.getExtensions().putAll(extensions); + + serviceContract.setInteractionScope(interactionScope); + return serviceContract; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java new file mode 100644 index 0000000000..b10474fb0f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.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.core.idl.java; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.EndsConversation; +import org.osoa.sca.annotations.OneWay; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.idl.InvalidConversationalOperationException; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.OverloadedOperationException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessor; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.Operation; +import static org.apache.tuscany.spi.model.Operation.CONVERSATION_END; +import static org.apache.tuscany.spi.model.Operation.NO_CONVERSATION; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName; + +/** + * Default implementation of an InterfaceJavaIntrospector. + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceProcessorRegistryImpl implements JavaInterfaceProcessorRegistry { + private static final String UNKNOWN_DATABINDING = null; + + private List processors = new ArrayList(); + + public JavaInterfaceProcessorRegistryImpl() { + } + + public void registerProcessor(JavaInterfaceProcessor processor) { + processors.add(processor); + } + + public void unregisterProcessor(JavaInterfaceProcessor processor) { + processors.remove(processor); + } + + public JavaServiceContract introspect(Class type) throws InvalidServiceContractException { + return introspect(type, true); + } + + public JavaServiceContract introspect(Class type, boolean deep) throws InvalidServiceContractException { + Class callbackClass = null; + Callback callback = type.getAnnotation(Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + callbackClass = callback.value(); + } else if (callback != null && Void.class.equals(callback.value())) { + throw new IllegalCallbackException("No callback interface specified on annotation", type.getName()); + } + return introspect(type, callbackClass, deep); + } + public JavaServiceContract introspect(Class type, Class callback, boolean deep) + throws InvalidServiceContractException { + JavaServiceContract contract = new JavaServiceContract(); + contract.setInterfaceName(getBaseName(type)); + contract.setInterfaceClass(type); + if (callback != null) { + contract.setCallbackName(getBaseName(callback)); + contract.setCallbackClass(callback); + } + if (!deep) { + return contract; + } + boolean remotable = type.isAnnotationPresent(Remotable.class); + contract.setRemotable(remotable); + Scope interactionScope = type.getAnnotation(Scope.class); + boolean conversational = false; + if (interactionScope != null && "CONVERSATION".equalsIgnoreCase(interactionScope.value())) { + contract.setInteractionScope(InteractionScope.CONVERSATIONAL); + conversational = true; + } else { + contract.setInteractionScope(InteractionScope.NONCONVERSATIONAL); + } + contract.setOperations(getOperations(type, remotable, conversational)); + + if (callback != null) { + contract.setCallbackOperations(getOperations(callback, remotable, conversational)); + } + + for (JavaInterfaceProcessor processor : processors) { + processor.visitInterface(type, callback, contract); + } + return contract; + } + + private Map> getOperations(Class type, boolean remotable, boolean conversational) + throws InvalidServiceContractException { + Method[] methods = type.getMethods(); + Map> operations = new HashMap>(methods.length); + for (Method method : methods) { + String name = method.getName(); + if (remotable && operations.containsKey(name)) { + throw new OverloadedOperationException(method); + } + + Type returnType = method.getGenericReturnType(); + Type[] paramTypes = method.getGenericParameterTypes(); + Type[] faultTypes = method.getGenericExceptionTypes(); + boolean nonBlocking = method.isAnnotationPresent(OneWay.class); + int conversationSequence = NO_CONVERSATION; + if (method.isAnnotationPresent(EndsConversation.class)) { + if (!conversational) { + throw new InvalidConversationalOperationException( + "Method is marked as end conversation but contract is not conversational", + method.getDeclaringClass().getName(), + method); + } + conversationSequence = CONVERSATION_END; + } else if (conversational) { + conversationSequence = Operation.CONVERSATION_CONTINUE; + } + + DataType returnDataType = new DataType(UNKNOWN_DATABINDING, returnType, returnType); + List> paramDataTypes = new ArrayList>(paramTypes.length); + for (Type paramType : paramTypes) { + paramDataTypes.add(new DataType(UNKNOWN_DATABINDING, paramType, paramType)); + } + List> faultDataTypes = new ArrayList>(faultTypes.length); + for (Type faultType : faultTypes) { + faultDataTypes.add(new DataType(UNKNOWN_DATABINDING, faultType, faultType)); + } + + DataType>> inputType = + new DataType>>(DataBinding.IDL_INPUT, Object[].class, paramDataTypes); + Operation operation = new Operation(name, + inputType, + returnDataType, + faultDataTypes, + nonBlocking, + UNKNOWN_DATABINDING, + conversationSequence); + operations.put(name, operation); + } + return operations; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java new file mode 100644 index 0000000000..3dd1328b6a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessor; +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * Default implementation of the IntrospectionRegistry + * + * @version $Rev$ $Date$ + */ +public class IntrospectionRegistryImpl implements IntrospectionRegistry { + + private Monitor monitor; + private List cache = new ArrayList(); + + public IntrospectionRegistryImpl() { + } + + public IntrospectionRegistryImpl(Monitor monitor) { + this.monitor = monitor; + } + + @org.apache.tuscany.api.annotation.Monitor + public void setMonitor(Monitor monitor) { + this.monitor = monitor; + } + + public void registerProcessor(ImplementationProcessor processor) { + monitor.register(processor); + cache.add(processor); + } + + public void unregisterProcessor(ImplementationProcessor processor) { + monitor.unregister(processor); + cache.remove(processor); + } + + public PojoComponentType introspect(CompositeComponent parent, Class clazz, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + for (ImplementationProcessor processor : cache) { + processor.visitClass(parent, clazz, type, context); + } + + for (Constructor constructor : clazz.getConstructors()) { + for (ImplementationProcessor processor : cache) { + processor.visitConstructor(parent, constructor, type, context); + } + } + + Set methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz); + for (Method method : methods) { + for (ImplementationProcessor processor : cache) { + processor.visitMethod(parent, method, type, context); + } + } + + Set fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz); + for (Field field : fields) { + for (ImplementationProcessor processor : cache) { + processor.visitField(parent, field, type, context); + } + } + + Class superClass = clazz.getSuperclass(); + if (superClass != null) { + visitSuperClass(parent, superClass, type, context); + } + + for (ImplementationProcessor processor : cache) { + processor.visitEnd(parent, clazz, type, context); + } + return type; + } + + private void visitSuperClass(CompositeComponent parent, + Class clazz, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + if (!Object.class.equals(clazz)) { + for (ImplementationProcessor processor : cache) { + processor.visitSuperClass(parent, clazz, type, context); + } + clazz = clazz.getSuperclass(); + if (clazz != null) { + visitSuperClass(parent, clazz, type, context); + } + } + } + + public static interface Monitor { + void register(ImplementationProcessor processor); + + void unregister(ImplementationProcessor processor); + + void processing(ImplementationProcessor processor); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java new file mode 100644 index 0000000000..4ef4dc4d49 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java @@ -0,0 +1,282 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetInitializationException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.extension.AtomicComponentExtension; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.OutboundWire; + +import org.apache.tuscany.core.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.core.injection.ConversationIDObjectFactory; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.FieldInjector; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.InvalidAccessorException; +import org.apache.tuscany.core.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.core.injection.MethodInjector; +import org.apache.tuscany.core.injection.NoAccessorException; +import org.apache.tuscany.core.injection.NoMultiplicityTypeException; +import org.apache.tuscany.core.injection.ObjectCallbackException; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Base implementation of an {@link org.apache.tuscany.spi.component.AtomicComponent} whose type is a Java class + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class PojoAtomicComponent extends AtomicComponentExtension { + protected EventInvoker initInvoker; + protected EventInvoker destroyInvoker; + protected PojoObjectFactory instanceFactory; + protected List constructorParamNames; + protected Map referenceSites; + protected Map resourceSites; + protected Map propertySites; + protected Map callbackSites; + protected List> injectors; + protected Class implementationClass; + private List> constructorParamTypes = new ArrayList>(); + + public PojoAtomicComponent(PojoConfiguration configuration) { + super(configuration.getName(), + configuration.getParent(), + configuration.getWireService(), + configuration.getWorkContext(), + configuration.getScheduler(), + configuration.getMonitor(), + configuration.getInitLevel(), + configuration.getMaxIdleTime(), + configuration.getMaxAge()); + assert configuration.getInstanceFactory() != null : "Object factory was null"; + initInvoker = configuration.getInitInvoker(); + destroyInvoker = configuration.getDestroyInvoker(); + instanceFactory = configuration.getInstanceFactory(); + constructorParamNames = configuration.getConstructorParamNames(); + constructorParamTypes = configuration.getConstructorParamTypes(); + injectors = new ArrayList>(); + referenceSites = configuration.getReferenceSite() != null ? configuration.getReferenceSite() + : new HashMap(); + propertySites = configuration.getPropertySites() != null ? configuration.getPropertySites() + : new HashMap(); + resourceSites = configuration.getResourceSites() != null ? configuration.getResourceSites() + : new HashMap(); + callbackSites = configuration.getCallbackSite() != null ? configuration.getCallbackSite() + : new HashMap(); + implementationClass = configuration.getImplementationClass(); + } + + + public boolean isDestroyable() { + return destroyInvoker != null; + } + + public void init(Object instance) throws TargetInitializationException { + if (initInvoker != null) { + try { + initInvoker.invokeEvent(instance); + } catch (ObjectCallbackException e) { + throw new TargetInitializationException("Error initializing component instance", getName(), e); + } + } + } + + public void destroy(Object instance) throws TargetDestructionException { + if (destroyInvoker != null) { + try { + destroyInvoker.invokeEvent(instance); + } catch (ObjectCallbackException e) { + throw new TargetDestructionException("Error destroying component instance", getName(), e); + } + } + } + + public boolean isOptimizable() { + // stateless implementations that require a destroy callback cannot be optimized since the callback is + // performed by the JavaTargetInvoker + return !(getScope() == Scope.STATELESS && isDestroyable()); + } + + public Object getTargetInstance() throws TargetResolutionException { + return scopeContainer.getInstance(this); + } + + public Object getAssociatedTargetInstance() throws TargetResolutionException { + return scopeContainer.getAssociatedInstance(this); + } + + public Object createInstance() throws ObjectCreationException { + Object instance = instanceFactory.getInstance(); + // inject the instance with properties and references + for (Injector injector : injectors) { + injector.inject(instance); + } + return instance; + } + + public void addPropertyFactory(String name, ObjectFactory factory) { + Member member = propertySites.get(name); + if (member instanceof Field) { + injectors.add(new FieldInjector((Field) member, factory)); + } else if (member instanceof Method) { + injectors.add(new MethodInjector((Method) member, factory)); + } + // cycle through constructor param names as well + for (int i = 0; i < constructorParamNames.size(); i++) { + if (name.equals(constructorParamNames.get(i))) { + ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories(); + initializerFactories[i] = factory; + break; + } + } + //FIXME throw an error if no injection site found + } + + public void addResourceFactory(String name, ObjectFactory factory) { + Member member = resourceSites.get(name); + if (member instanceof Field) { + injectors.add(new FieldInjector((Field) member, factory)); + } else if (member instanceof Method) { + injectors.add(new MethodInjector((Method) member, factory)); + } + // cycle through constructor param names as well + for (int i = 0; i < constructorParamNames.size(); i++) { + if (name.equals(constructorParamNames.get(i))) { + ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories(); + initializerFactories[i] = factory; + break; + } + } + //FIXME throw an error if no injection site found + } + + public void addConversationIDFactory(Member member) { + ObjectFactory convIDObjectFactory = new ConversationIDObjectFactory(workContext); + if (member instanceof Field) { + injectors.add(new FieldInjector((Field) member, convIDObjectFactory)); + } else if (member instanceof Method) { + injectors.add(new MethodInjector((Method) member, convIDObjectFactory)); + } else { + throw new InvalidAccessorException("Member must be a field or method", member.getName()); + } + } + + protected void onReferenceWire(OutboundWire wire) { + String name = wire.getReferenceName(); + Member member = referenceSites.get(name); + if (member != null) { + injectors.add(createInjector(member, wire)); + } + // cycle through constructor param names as well + for (int i = 0; i < constructorParamNames.size(); i++) { + if (name.equals(constructorParamNames.get(i))) { + ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories(); + initializerFactories[i] = createWireFactory(constructorParamTypes.get(i), wire); + break; + } + } + //TODO error if ref not set on constructor or ref site + } + + public void onReferenceWires(List wires) { + assert wires.size() > 0 : "Wires were empty"; + String referenceName = wires.get(0).getReferenceName(); + Member member = referenceSites.get(referenceName); + if (member == null) { + if (constructorParamNames.contains(referenceName)) { + // injected on the constructor + + } else { + throw new NoAccessorException(referenceName); + } + } + Class type = wires.get(0).getServiceContract().getInterfaceClass(); + if (type == null) { + throw new NoMultiplicityTypeException("Java interface must be specified for multiplicity", referenceName); + } + injectors.add(createMultiplicityInjector(member, type, wires)); + //TODO multiplicity for constructor injection + } + + public boolean implementsCallback(Class callbackClass) { + Class[] implementedInterfaces = implementationClass.getInterfaces(); + for (Class implementedInterface : implementedInterfaces) { + if (implementedInterface.isAssignableFrom(callbackClass)) { + return true; + } + } + + return false; + } + + protected Injector createInjector(Member member, OutboundWire wire) { + if (member instanceof Field) { + Class type = ((Field) member).getType(); + ObjectFactory factory = createWireFactory(type, wire); + return new FieldInjector((Field) member, factory); + } else if (member instanceof Method) { + Class type = ((Method) member).getParameterTypes()[0]; + ObjectFactory factory = createWireFactory(type, wire); + return new MethodInjector((Method) member, factory); + } else { + throw new InvalidAccessorException("Member must be a field or method", member.getName()); + } + } + + protected Injector createMultiplicityInjector(Member member, + Class interfaceType, + List wireFactories) { + List> factories = new ArrayList>(); + for (OutboundWire wire : wireFactories) { + factories.add(createWireFactory(interfaceType, wire)); + } + if (member instanceof Field) { + Field field = (Field) member; + if (field.getType().isArray()) { + return new FieldInjector(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector(field, new ListMultiplicityObjectFactory(factories)); + } + } else if (member instanceof Method) { + Method method = (Method) member; + 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", member.getName()); + } + } + + protected abstract ObjectFactory createWireFactory(Class interfaze, OutboundWire wire); + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java new file mode 100644 index 0000000000..104b1f647e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +import java.lang.reflect.Member; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.extension.ExecutionMonitor; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Encapsulates confuration for a Java-based atomic component + * + * @version $Rev$ $Date$ + */ +public class PojoConfiguration { + private String name; + private CompositeComponent parent; + //private ScopeContainer scopeContainer; + private PojoObjectFactory instanceFactory; + private List constructorParamNames = new ArrayList(); + private List> constructorParamTypes = new ArrayList>(); + private int initLevel; + private EventInvoker initInvoker; + private EventInvoker destroyInvoker; + private List propertyInjectors = new ArrayList(); + private Map referenceSites = new HashMap(); + private Map propertySites = new HashMap(); + private Map resourceSites = new HashMap(); + private Map callbackSites = new HashMap(); + private WireService wireService; + private WorkContext workContext; + private WorkScheduler scheduler; + private ExecutionMonitor monitor; + private long maxIdleTime = -1; + private long maxAge = -1; + private Class implementationClass; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public CompositeComponent getParent() { + return parent; + } + + public void setParent(CompositeComponent parent) { + this.parent = parent; + } + + public PojoObjectFactory getInstanceFactory() { + return instanceFactory; + } + + public void setInstanceFactory(PojoObjectFactory objectFactory) { + this.instanceFactory = objectFactory; + } + + public List getConstructorParamNames() { + return constructorParamNames; + } + + public void setConstructorParamNames(List names) { + constructorParamNames = names; + } + + public void addConstructorParamName(String name) { + constructorParamNames.add(name); + } + + public List> getConstructorParamTypes() { + return constructorParamTypes; + } + + public void setConstructorParamTypes(List> constructorParamTypes) { + this.constructorParamTypes = constructorParamTypes; + } + + public void addConstructorParamType(Class type) { + constructorParamTypes.add(type); + } + + public int getInitLevel() { + return initLevel; + } + + public void setInitLevel(int initLevel) { + this.initLevel = initLevel; + } + + public long getMaxIdleTime() { + return maxIdleTime; + } + + public void setMaxIdleTime(long maxIdleTime) { + this.maxIdleTime = maxIdleTime; + } + + public long getMaxAge() { + return maxAge; + } + + public void setMaxAge(long maxAge) { + this.maxAge = maxAge; + } + + public EventInvoker getInitInvoker() { + return initInvoker; + } + + public void setInitInvoker(EventInvoker initInvoker) { + this.initInvoker = initInvoker; + } + + public EventInvoker getDestroyInvoker() { + return destroyInvoker; + } + + public void setDestroyInvoker(EventInvoker destroyInvoker) { + this.destroyInvoker = destroyInvoker; + } + + public List getPropertyInjectors() { + return propertyInjectors; + } + + public void addPropertyInjector(Injector injector) { + propertyInjectors.add(injector); + } + + public Map getReferenceSite() { + return referenceSites; + } + + public void addReferenceSite(String name, Member member) { + referenceSites.put(name, member); + } + + public Map getResourceSites() { + return resourceSites; + } + + public void addResourceSite(String name, Member member) { + resourceSites.put(name, member); + } + + public Map getCallbackSite() { + return callbackSites; + } + + public void addCallbackSite(String name, Member member) { + callbackSites.put(name, member); + } + + public Map getPropertySites() { + return propertySites; + } + + public void addPropertySite(String name, Member member) { + propertySites.put(name, member); + } + + public WireService getWireService() { + return wireService; + } + + public void setWireService(WireService wireService) { + this.wireService = wireService; + } + + public WorkContext getWorkContext() { + return workContext; + } + + public void setWorkContext(WorkContext workContext) { + this.workContext = workContext; + } + + public WorkScheduler getScheduler() { + return scheduler; + } + + public void setScheduler(WorkScheduler scheduler) { + this.scheduler = scheduler; + } + + public ExecutionMonitor getMonitor() { + return monitor; + } + + public void setMonitor(ExecutionMonitor monitor) { + this.monitor = monitor; + } + + public Class getImplementationClass() { + return implementationClass; + } + + public void setImplementationClass(Class implementationClass) { + this.implementationClass = implementationClass; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java new file mode 100644 index 0000000000..293ef81b3b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeBuilder.java @@ -0,0 +1,61 @@ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.builder.BuilderInstantiationException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.ComponentRegistrationException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeReferenceDefinition; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Abstract builder for composites + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractCompositeBuilder> extends + ComponentBuilderExtension { + + public CompositeComponent build(CompositeComponent parent, + CompositeComponent component, + CompositeComponentType componentType, + DeploymentContext deploymentContext) throws BuilderException { + + for (ComponentDefinition> definition : componentType.getComponents().values()) { + try { + Component child = builderRegistry.build(component, definition, deploymentContext); + component.register(child); + } catch (ComponentRegistrationException e) { + throw new BuilderInstantiationException("Error registering component", e); + } + } + for (ServiceDefinition definition : componentType.getServices().values()) { + try { + Service service = builderRegistry.build(component, definition, deploymentContext); + component.register(service); + } catch (ComponentRegistrationException e) { + throw new BuilderInstantiationException("Error registering service", e); + } + } + for (CompositeReferenceDefinition definition : componentType.getReferences().values()) { + try { + Reference child = builderRegistry.build(component, definition, deploymentContext); + component.register(child); + } catch (ComponentRegistrationException e) { + throw new BuilderInstantiationException("Error registering reference", e); + } + } + return component; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java new file mode 100644 index 0000000000..0f10703802 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.ComponentRegistrationException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetInvokerCreationException; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.extension.CompositeComponentExtension; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; + +/** + * The base implementation of a composite context + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractCompositeComponent extends CompositeComponentExtension { + public static final int DEFAULT_WAIT = 1000 * 60; + // Blocking latch to ensure the composite is initialized exactly once prior to servicing requests + protected CountDownLatch initializeLatch = new CountDownLatch(1); + protected final Object lock = new Object(); + // Indicates whether the composite context has been initialized + protected boolean initialized; + + + /** + * @param name the name of the SCA composite + * @param parent the SCA composite parent + * @param connector the connector for fusing wires + * @param propertyValues the values of this composite's Properties + */ + public AbstractCompositeComponent(String name, + CompositeComponent parent, + Connector connector, + Map propertyValues) { + super(name, parent, connector, propertyValues); + } + + public void registerJavaObject(String name, Class service, I instance) + throws ComponentRegistrationException { + register(new SystemSingletonAtomicComponent(name, this, service, instance)); + } + + public void registerJavaObject(String name, List> services, I instance) + throws ComponentRegistrationException { + register(new SystemSingletonAtomicComponent(name, this, services, instance)); + } + + public void start() { + synchronized (lock) { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Composite not in UNINITIALIZED state"); + } + + for (SCAObject child : systemChildren.values()) { + child.start(); + } + for (SCAObject child : children.values()) { + child.start(); + } + initializeLatch.countDown(); + initialized = true; + lifecycleState = INITIALIZED; + } + publish(new CompositeStart(this, this)); + } + + public void stop() { + if (lifecycleState == STOPPED) { + return; + } + + for (SCAObject child : children.values()) { + child.stop(); + } + for (SCAObject child : systemChildren.values()) { + child.stop(); + } + publish(new CompositeStop(this, this)); + // need to block a start until reset is complete + initializeLatch = new CountDownLatch(2); + lifecycleState = STOPPING; + initialized = false; + // allow initialized to be called + initializeLatch.countDown(); + lifecycleState = STOPPED; + } + + public void publish(Event event) { + if (lifecycleState == STOPPED) { + return; + } + checkInit(); + super.publish(event); + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation, InboundWire callbackWire) + throws TargetInvokerCreationException { + return null; + } + + /** + * Blocks until the composite context has been initialized + */ + protected void checkInit() throws ComponentTimeoutException { + if (!initialized) { + try { + /* block until the composite has initialized */ + boolean success = initializeLatch.await(AbstractCompositeComponent.DEFAULT_WAIT, + TimeUnit.MILLISECONDS); + if (!success) { + throw new ComponentTimeoutException("Timeout waiting for context to initialize"); + } + } catch (InterruptedException e) { // should not happen + } + } + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java new file mode 100644 index 0000000000..9aaf677be8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeContext.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.osoa.sca.CompositeContext; +import org.osoa.sca.ServiceRuntimeException; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Wire; +import org.apache.tuscany.spi.wire.WireService; + +/** + * Base implementation of the {@link org.osoa.sca.CompositeContext} + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractCompositeContext implements CompositeContext { + protected final CompositeComponent composite; + protected final WireService wireService; + + public AbstractCompositeContext(final CompositeComponent composite, final WireService wireService) { + this.composite = composite; + this.wireService = wireService; + } + + public String getName() { + return composite.getName(); + } + + public String getURI() { + throw new UnsupportedOperationException(); + } + + public T locateService(Class serviceInterface, String serviceName) throws ServiceRuntimeException { + QualifiedName qName = new QualifiedName(serviceName); + if (qName.getPortName() == null) { + String name = serviceInterface.getSimpleName(); + qName = new QualifiedName(qName.getPartName(), name); + } + SCAObject child = composite.getChild(qName.getPartName()); + InboundWire wire = getInboundWire(child, qName); + if (wire.isOptimizable() + && wire.getServiceContract().getInterfaceClass() != null + && serviceInterface.isAssignableFrom(wire.getServiceContract().getInterfaceClass())) { + try { + return serviceInterface.cast(wire.getTargetService()); + } catch (TargetResolutionException e) { + throw new ServiceRuntimeException(e); + } + } + return wireService.createProxy(serviceInterface, wire); + } + + protected InboundWire getInboundWire(SCAObject child, QualifiedName qName) { + InboundWire wire = null; + if (child instanceof Component) { + wire = ((Component) child).getInboundWire(qName.getPortName()); + if (wire == null) { + throw new ServiceRuntimeException("Service not found [" + qName + "]"); + } + } else if (child instanceof Service) { + Service service = (Service) child; + for (ServiceBinding binding : service.getServiceBindings()) { + if (Wire.LOCAL_BINDING.equals(binding.getInboundWire().getBindingType())) { + wire = binding.getInboundWire(); + break; + } + } + if (wire == null) { + throw new ServiceRuntimeException("Local binding for service not found [" + qName + "]"); + } + } else if (child instanceof Reference) { + Reference service = (Reference) child; + if (service.getReferenceBindings().isEmpty()) { + throw new ServiceRuntimeException("No binding for reference [" + qName + "]"); + } + for (ReferenceBinding binding : service.getReferenceBindings()) { + if (Wire.LOCAL_BINDING.equals(binding.getInboundWire().getBindingType())) { + wire = binding.getInboundWire(); + break; + } + } + if (wire == null) { + // pick the first one + wire = service.getReferenceBindings().get(0).getInboundWire(); + } + } else if (child == null) { + throw new ServiceRuntimeException("Service not found [" + qName + "]"); + } else { + throw new ServiceRuntimeException("Invalid service type [" + child.getClass().getName() + "]"); + } + return wire; + } + + public CompositeComponent getComposite() { + return composite; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java new file mode 100644 index 0000000000..ed64cb1236 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ComponentTimeoutException.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.component.ComponentRuntimeException; + +/** + * Denotes a condition where a component times out waiting to perform an operation + * + * @version $Rev$ $Date$ + */ +public class ComponentTimeoutException extends ComponentRuntimeException { + + public ComponentTimeoutException(String message) { + super(message); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java new file mode 100644 index 0000000000..008c99db8d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; + +/** + * Instantiates a composite component from an assembly definition + * + * @version $Rev$ $Date$ + */ +public class CompositeBuilder extends AbstractCompositeBuilder { + + public Component build(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext deploymentContext) throws BuilderException { + CompositeImplementation implementation = componentDefinition.getImplementation(); + CompositeComponentType componentType = implementation.getComponentType(); + String name = componentDefinition.getName(); + CompositeComponentImpl component = new CompositeComponentImpl(name, parent, connector, null); + + return build(parent, component, componentType, deploymentContext); + } + + protected Class getImplementationType() { + return CompositeImplementation.class; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java new file mode 100644 index 0000000000..75bc2d8c78 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.Map; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; + +/** + * The standard implementation of a composite component. Autowiring is performed by delegating to the parent composite. + * + * @version $Rev$ $Date$ + */ +public class CompositeComponentImpl extends AbstractCompositeComponent { + private String uri; + private boolean systemComposite; + + /** + * Constructor specifying property values + * + * @param name the name of this Component + * @param parent this component's parent + * @param connector the connector to use for wires + * @param propertyValues this composite's Property values + */ + public CompositeComponentImpl(String name, + CompositeComponent parent, + Connector connector, + Map propertyValues) { + this(name, null, parent, connector, propertyValues); + } + + /** + * Constructor specifying if the composite is a system composite + * + * @param name the name of this Component + * @param parent this component's parent + * @param connector the connector to use for wires + * @param systemComposite true if the composite is a system composite + */ + public CompositeComponentImpl(String name, + CompositeComponent parent, + Connector connector, + boolean systemComposite) { + this(name, null, parent, connector, null, systemComposite); + } + + /** + * Constructor specifying name and URI. + * + * @param name the name of this Component + * @param uri the unique identifier for this component + * @param parent this component's parent + * @param connector the connector to use for wires + * @param propertyValues this composite's Property values + */ + public CompositeComponentImpl(String name, + String uri, + CompositeComponent parent, + Connector connector, + Map propertyValues) { + super(name, parent, connector, propertyValues); + this.uri = uri; + } + + /** + * Constructor specifying name and URI. + * + * @param name the name of this Component + * @param uri the unique identifier for this component + * @param parent this component's parent + * @param connector the connector to use for wires + * @param propertyValues this composite's Property values + * @param systemComposite true if the composite is a system composite + */ + public CompositeComponentImpl(String name, + String uri, + CompositeComponent parent, + Connector connector, + Map propertyValues, + boolean systemComposite) { + super(name, parent, connector, propertyValues); + this.uri = uri; + this.systemComposite = systemComposite; + } + + public String getURI() { + return uri; + } + + public boolean isSystem() { + return systemComposite; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java new file mode 100644 index 0000000000..c55f1b8ffa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.URL; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; + +import org.apache.tuscany.core.deployer.ChildDeploymentContext; + +/** + * Loads a composite component type + * + * @version $Rev$ $Date$ + */ +public class CompositeComponentTypeLoader extends ComponentTypeLoaderExtension { + public CompositeComponentTypeLoader() { + } + + public CompositeComponentTypeLoader(LoaderRegistry loaderRegistry) { + super(loaderRegistry); + } + + protected Class getImplementationClass() { + return CompositeImplementation.class; + } + + public void load(CompositeComponent parent, CompositeImplementation implementation, + DeploymentContext deploymentContext) + throws LoaderException { + URL scdlLocation = implementation.getScdlLocation(); + ClassLoader cl = new CompositeClassLoader(implementation.getClassLoader()); + deploymentContext = new ChildDeploymentContext(deploymentContext, cl, scdlLocation); + CompositeComponentType componentType = loadFromSidefile(parent, scdlLocation, deploymentContext); + implementation.setComponentType(componentType); + } + + protected CompositeComponentType loadFromSidefile(CompositeComponent parent, + URL url, + DeploymentContext deploymentContext) + throws LoaderException { + return loaderRegistry.load(parent, null, url, CompositeComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java new file mode 100644 index 0000000000..c268d342b5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java @@ -0,0 +1,426 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import static org.osoa.sca.Constants.SCA_NS; + +import java.net.URI; +import java.net.URL; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.property.PropertyHelper; +import org.apache.tuscany.core.util.ReferenceLoaderHelper; +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.loader.InvalidPromotedReferenceException; +import org.apache.tuscany.spi.loader.InvalidServiceException; +import org.apache.tuscany.spi.loader.InvalidWireException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.ReferenceMultiplicityOverridingException; +import org.apache.tuscany.spi.model.BindingDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentReferenceDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeReferenceDefinition; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Include; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.model.WireDefinition; +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * Loads a composite component definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class CompositeLoader extends LoaderExtension { + public static final QName COMPOSITE = new QName(SCA_NS, "composite"); + public static final String URI_DELIMITER = "/"; + + @Autowire + protected JavaInterfaceProcessorRegistry processorRegistry; + + private final ArtifactRepository artifactRepository; + + public CompositeLoader(@Autowire + LoaderRegistry registry, @Autowire + ArtifactRepository artifactRepository) { + super(registry); + this.artifactRepository = artifactRepository; + } + + public QName getXMLType() { + return COMPOSITE; + } + + public CompositeComponentType load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, + LoaderException { + CompositeComponentType> composite = + new CompositeComponentType>(); + composite.setName(reader.getAttributeValue(null, "name")); + boolean done = false; + while (!done) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, composite, reader, deploymentContext); + if (o instanceof ServiceDefinition) { + composite.add((ServiceDefinition)o); + } else if (o instanceof CompositeReferenceDefinition) { + composite.add((CompositeReferenceDefinition)o); + } else if (o instanceof Property) { + composite.add((Property)o); + } else if (o instanceof ComponentDefinition) { + composite.add((ComponentDefinition)o); + } else if (o instanceof Include) { + composite.add((Include)o); + } else if (o instanceof Dependency) { + Artifact artifact = ((Dependency)o).getArtifact(); + if (artifactRepository != null) { + // default to jar type if not specified + if (artifact.getType() == null) { + artifact.setType("jar"); + } + artifactRepository.resolve(artifact); + } + if (artifact.getUrl() != null) { + ClassLoader classLoader = deploymentContext.getClassLoader(); + if (classLoader instanceof CompositeClassLoader) { + CompositeClassLoader ccl = (CompositeClassLoader)classLoader; + for (URL dep : artifact.getUrls()) { + ccl.addURL(dep); + } + } + } + } else if (o instanceof WireDefinition) { + composite.add((WireDefinition)o); + } else { + // add as an unknown model extension + if (o != null) { + composite.getDeclaredExtensions().put(o.getClass(), o); + } + } + reader.next(); + break; + case END_ELEMENT: + if (COMPOSITE.equals(reader.getName())) { + // if there are wire defintions then link them up to the + // relevant components + resolveWires(composite); + validateCompositeDefintion(composite); + //verifyCompositeCompleteness(composite); + done = true; + break; + } + } + } + processJavaInterfaces(composite); + for (ComponentDefinition> c : composite.getComponents() + .values()) { + processJavaInterfaces(c.getImplementation().getComponentType()); + PropertyHelper.processProperties(composite, c, deploymentContext); + } + return composite; + } + + protected void processJavaInterfaces(ComponentType componentType) throws LoaderException { + if (processorRegistry == null) { + return; + } + try { + for (Object s : componentType.getServices().values()) { + ServiceContract contract = ((ServiceDefinition)s).getServiceContract(); + if (JavaServiceContract.class.isInstance(contract)) { + contract = + processorRegistry.introspect(contract.getInterfaceClass(), contract + .getCallbackClass(), true); + ((ServiceDefinition)s).setServiceContract(contract); + } + } + for (Object r : componentType.getReferences().values()) { + ServiceContract contract = ((AbstractReferenceDefinition)r).getServiceContract(); + if (JavaServiceContract.class.isInstance(contract)) { + contract = + processorRegistry.introspect(contract.getInterfaceClass(), contract + .getCallbackClass(), true); + ((AbstractReferenceDefinition)r).setServiceContract(contract); + } + } + } catch (InvalidServiceContractException e) { + throw new LoaderException(e); + } + + } + + protected void resolveWires(CompositeComponentType> composite) throws InvalidWireException, + InvalidPromotedReferenceException { + QualifiedName sourceName; + ComponentDefinition componentDefinition; + ServiceDefinition serviceDefinition; + List wireDefns = composite.getDeclaredWires(); + for (WireDefinition wire : wireDefns) { + URI targetUri = wire.getTarget(); + // validate the target before finding the source + validateTarget(targetUri, composite); + + sourceName = new QualifiedName(wire.getSource().getPath()); + serviceDefinition = composite.getDeclaredServices().get(sourceName.getPartName()); + if (serviceDefinition != null) { + serviceDefinition.setTarget(wire.getTarget()); + } else { + componentDefinition = + composite.getDeclaredComponents().get(sourceName.getPartName()); + if (componentDefinition != null) { + if (sourceName.getPortName() == null || sourceName.getPortName().length() == 0) { + if (componentDefinition.getReferences().size() > 1 || componentDefinition + .getReferences().isEmpty()) { + throw new InvalidWireException("Unable to determine unique source reference"); + } else { + ComponentReferenceDefinition ref = + (ComponentReferenceDefinition)componentDefinition.getReferences() + .values().iterator().next(); + ref.addTarget(targetUri); + } + } else { + ((ComponentReferenceDefinition)componentDefinition.getReferences() + .get(sourceName.getPortName())).addTarget(targetUri); + } + + } else { + throw new InvalidWireException("Source not found", sourceName.toString()); + } + } + } + + QualifiedName targetName = null; + ComponentReferenceDefinition promotedComponentRef = null; + for (CompositeReferenceDefinition compositeRefDef : composite.getDeclaredReferences() + .values()) { + for (URI promotedComponentRefUri : compositeRefDef.getPromotedReferences()) { + targetName = new QualifiedName(promotedComponentRefUri.toString()); + componentDefinition = composite.getComponents().get(targetName.getPartName()); + if (componentDefinition != null) { + if (targetName.getPortName() != null) { + promotedComponentRef = + (ComponentReferenceDefinition)componentDefinition.getReferences() + .get(targetName.getPortName()); + } else { + promotedComponentRef = + (ComponentReferenceDefinition)componentDefinition.getReferences() + .values().iterator().next(); + } + if (promotedComponentRef != null) { + promotedComponentRef.addTarget(URI.create(compositeRefDef.getName())); + } else { + throw new InvalidPromotedReferenceException("Invalid promoted reference ", + targetName.toString()); + } + } else { + throw new InvalidPromotedReferenceException("Invalid promoted reference ", + targetName.toString()); + } + + } + } + } + + protected void validateCompositeDefintion( + CompositeComponentType> composite) + throws LoaderException { + verifyCompositeCompleteness(composite); + validateCompositeReferenceDefinition(composite); + } + + protected void verifyCompositeCompleteness( + CompositeComponentType> composite) + throws InvalidServiceException { + // check if all of the composite services have been wired + for (ServiceDefinition svcDefn : composite.getDeclaredServices().values()) { + if (svcDefn.getTarget() == null) { + throw new InvalidServiceException("Composite service not wired to a target", + svcDefn.getName()); + } + } + } + + protected void verifyReferenceInterfaceCompatibility(CompositeReferenceDefinition compositeRefDefn, + ComponentReferenceDefinition componentRefDefn) + throws LoaderException { + if (compositeRefDefn.getServiceContract() != null) { + //TODO : Since the JavaInterfaceProcessorRegistryImpl does not do a deep introspection + //this comparison is not possible. This will be uncommented once that is fixed. + /*ReferenceLoaderHelper.checkInterfaceCompatibility(componentRefDefn.getServiceContract(), + compositeRefDefn.getServiceContract(), + false);*/ + } else { + //FIXME : the wireservice needs a service contract in the composite ref. def + //so filling up with one of the promoted component ref. defn's service contract + compositeRefDefn.setServiceContract(componentRefDefn.getServiceContract()); + } + } + + protected Multiplicity deriveReferenceMultiplicity(CompositeReferenceDefinition compositeRefDefn, + ComponentReferenceDefinition componentRefDefn, + Multiplicity leastMultiplicity) + throws LoaderException + { + if (compositeRefDefn.getMultiplicity() != null) { + if (!ReferenceLoaderHelper. + isValidMultiplicityOverride(componentRefDefn.getMultiplicity(), + compositeRefDefn.getMultiplicity())) { + throw new ReferenceMultiplicityOverridingException(compositeRefDefn.getName(), + componentRefDefn.getMultiplicity(), + compositeRefDefn.getMultiplicity()); + } + } else { + if (leastMultiplicity != null) { + if (!ReferenceLoaderHelper.isCompatibleMultiplicity(componentRefDefn.getMultiplicity(), + leastMultiplicity)) { + throw new ReferenceMultiplicityOverridingException(compositeRefDefn.getName(), + componentRefDefn.getMultiplicity(), + leastMultiplicity); + } else { + if (!ReferenceLoaderHelper. + isValidMultiplicityOverride(componentRefDefn.getMultiplicity(), + leastMultiplicity)) { + leastMultiplicity = componentRefDefn.getMultiplicity(); + } + } + } + else { + leastMultiplicity = componentRefDefn.getMultiplicity(); + } + } + return leastMultiplicity; + } + + protected void validateCompositeReferenceDefinition(CompositeComponentType> composite) throws LoaderException { + QualifiedName promotedName = null; + ComponentDefinition promotedComponentDefinition = null; + ComponentReferenceDefinition promotedComponentReference = null; + + for (CompositeReferenceDefinition compositeRefDefn : composite.getDeclaredReferences().values()) { + // ensure if there is a service contract defined, then it is + // compatible with all + // promoted component reference interfaces + Multiplicity leastMultiplicity = null; + boolean bindingsOverriden = compositeRefDefn.getBindings().size() > 0; + for (URI promotedRef : compositeRefDefn.getPromotedReferences()) { + // check for valid promotions + promotedName = new QualifiedName(promotedRef.toString()); + promotedComponentDefinition = + composite.getComponents().get(promotedName.getPartName()); + if (promotedComponentDefinition != null) { + if (promotedName.getPortName() != null) { + promotedComponentReference = + (ComponentReferenceDefinition)promotedComponentDefinition + .getReferences().get(promotedName.getPortName()); + } else { + promotedComponentReference = + (ComponentReferenceDefinition)promotedComponentDefinition + .getReferences().values().iterator().next(); + } + // check for service contract compatibility + if (promotedComponentReference != null) { + verifyReferenceInterfaceCompatibility(compositeRefDefn, + promotedComponentReference); + leastMultiplicity = + deriveReferenceMultiplicity(compositeRefDefn, + promotedComponentReference, + leastMultiplicity); + + // if bindings have not been overridden int the composite then copy them + // over for convenience so that when accessed, traversing of all promoted + // references can be avoided + if (!bindingsOverriden) { + for (BindingDefinition refBinding : promotedComponentReference + .getBindings()) { + compositeRefDefn.addBinding((BindingDefinition)refBinding.clone()); + } + } + } else { + throw new InvalidPromotedReferenceException("Invalid promoted reference ", + promotedRef.toString()); + } + } else { + throw new InvalidPromotedReferenceException("Invalid promoted reference ", + promotedRef.toString()); + } + + } + if (compositeRefDefn.getMultiplicity() == null) { + compositeRefDefn.setMultiplicity(leastMultiplicity); + } + + } + } + + private void validateTarget(URI target, + CompositeComponentType> composite) throws InvalidWireException { + QualifiedName targetName = new QualifiedName(target.getPath()); + // if target is not a reference of the composite + if (composite.getReferences().get(targetName.getPartName()) == null) { + ComponentDefinition targetDefinition = + composite.getDeclaredComponents().get(targetName.getPartName()); + // if a target component exists in this composite + if (targetDefinition != null) { + Implementation implementation = targetDefinition.getImplementation(); + ComponentType componentType = implementation.getComponentType(); + Map services = componentType.getServices(); + if (targetName.getPortName() == null) { + if (services.size() > 1 || services.isEmpty()) { + throw new InvalidWireException("Ambiguous target", targetName.toString()); + } + } else { + if (services.get(targetName.getPortName()) == null) { + throw new InvalidWireException("Invalid target service", targetName + .toString()); + } + } + } else { + throw new InvalidWireException("Target not found", targetName.toString()); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java new file mode 100644 index 0000000000..808f36072f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.services.artifact.Artifact; + +/** + * A model object that represents a dependency on an external artifact. + * + * @version $Rev$ $Date$ + */ +public class Dependency extends ModelObject { + private Artifact artifact; + + public Artifact getArtifact() { + return artifact; + } + + public void setArtifact(Artifact artifact) { + this.artifact = artifact; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java new file mode 100644 index 0000000000..ac744d5905 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Set; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.osoa.sca.Constants; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * Loader that handles an <implementation.composite> element. + * + * @version $Rev$ $Date$ + */ +public class ImplementationCompositeLoader extends LoaderExtension { + private static final QName IMPLEMENTATION_COMPOSITE = + new QName(Constants.SCA_NS, "implementation.composite"); + + private final ArtifactRepository artifactRepository; + + public ImplementationCompositeLoader(@Autowire LoaderRegistry registry, + @Autowire ArtifactRepository artifactRepository) { + super(registry); + this.artifactRepository = artifactRepository; + } + + public QName getXMLType() { + return IMPLEMENTATION_COMPOSITE; + } + + public CompositeImplementation load(CompositeComponent parent, + ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + assert IMPLEMENTATION_COMPOSITE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String group = reader.getAttributeValue(null, "group"); + String version = reader.getAttributeValue(null, "version"); + String scdlLocation = reader.getAttributeValue(null, "scdlLocation"); + String jarLocation = reader.getAttributeValue(null, "jarLocation"); + LoaderUtil.skipToEndElement(reader); + + CompositeImplementation impl = new CompositeImplementation(); + impl.setName(name); + if (scdlLocation != null) { + try { + impl.setScdlLocation(new URL(deploymentContext.getScdlLocation(), scdlLocation)); + } catch (MalformedURLException e) { + throw new InvalidValueException(scdlLocation, name, e); + } + impl.setClassLoader(deploymentContext.getClassLoader()); + } else if (jarLocation != null) { + URL jarUrl; + try { + jarUrl = new URL(deploymentContext.getScdlLocation(), jarLocation); + } catch (MalformedURLException e) { + throw new InvalidValueException(jarLocation, name, e); + } + try { + impl.setScdlLocation(new URL("jar:" + jarUrl.toExternalForm() + "!/META-INF/sca/default.scdl")); + } catch (MalformedURLException e) { + throw new AssertionError("Could not convert URL to a jar: url"); + } + impl.setClassLoader(new CompositeClassLoader(new URL[]{jarUrl}, deploymentContext.getClassLoader())); + } else if (artifactRepository != null && group != null && version != null) { + Artifact artifact = new Artifact(); + artifact.setGroup(group); + artifact.setName(name); + artifact.setVersion(version); + artifact.setType("jar"); + artifactRepository.resolve(artifact); + if (artifact.getUrl() == null) { + throw new MissingResourceException(artifact.toString(), name); + } + try { + impl.setScdlLocation(new URL("jar:" + artifact.getUrl() + "!/META-INF/sca/default.scdl")); + } catch (MalformedURLException e) { + throw new AssertionError(e); + } + Set artifactURLs = artifact.getUrls(); + URL[] urls = new URL[artifactURLs.size()]; + int i = 0; + for (URL artifactURL : artifactURLs) { + urls[i++] = artifactURL; + } + impl.setClassLoader(new CompositeClassLoader(urls, deploymentContext.getClassLoader())); + } + return impl; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java new file mode 100644 index 0000000000..f2a8109ee3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ManagedRequestContext.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import javax.security.auth.Subject; + +import org.osoa.sca.RequestContext; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.CallableReference; + +import org.apache.tuscany.spi.component.WorkContext; + +/** + * @version $Rev$ $Date$ + */ +public class ManagedRequestContext implements RequestContext { + private WorkContext workContext; + + public ManagedRequestContext(WorkContext workContext) { + this.workContext = workContext; + } + + public Subject getSecuritySubject() { + throw new UnsupportedOperationException(); + } + + public String getServiceName() { + return workContext.getCurrentServiceName(); + } + + public ServiceReference getServiceReference() { + throw new UnsupportedOperationException(); + } + + public CB getCallback() { + throw new UnsupportedOperationException(); + } + + public CallableReference getCallbackReference() { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java new file mode 100644 index 0000000000..3fcba7b054 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ReferenceImpl.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.spi.component.AbstractSCAObject; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; + +/** + * The default implementation of a {@link org.apache.tuscany.spi.component.Reference} + * + * @version $Rev$ $Date$ + */ +public class ReferenceImpl extends AbstractSCAObject implements Reference { + private ServiceContract serviceContract; + private List bindings = new ArrayList(); + private boolean system; + + public ReferenceImpl(String name, CompositeComponent parent, ServiceContract contract) { + this(name, parent, contract, false); + } + + public ReferenceImpl(String name, + CompositeComponent parent, + ServiceContract contract, + boolean system) { + super(name, parent); + this.serviceContract = contract; + this.system = system; + } + + public Scope getScope() { + return Scope.SYSTEM; + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public List getReferenceBindings() { + return Collections.unmodifiableList(bindings); + } + + public void addReferenceBinding(ReferenceBinding binding) { + binding.setReference(this); + bindings.add(binding); + } + + public void start() { + super.start(); + for (ReferenceBinding binding : bindings) { + binding.start(); + } + } + + public void stop() { + super.stop(); + for (ReferenceBinding binding : bindings) { + binding.stop(); + } + } + + @Override + public boolean isSystem() { + return system; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java new file mode 100644 index 0000000000..2db8519ccc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ServiceImpl.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.spi.component.AbstractSCAObject; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; + +/** + * The default implementation of a {@link Service} + * + * @version $Rev$ $Date$ + */ +public class ServiceImpl extends AbstractSCAObject implements Service { + private ServiceContract serviceContract; + private List bindings = new ArrayList(); + private boolean system; + private URI targetUri; + + public ServiceImpl(String name, CompositeComponent parent, ServiceContract contract) { + this(name, parent, contract, null, false); + } + + public ServiceImpl(String name, + CompositeComponent parent, + ServiceContract contract, + URI targetUri, + boolean system) { + super(name, parent); + this.serviceContract = contract; + this.system = system; + this.targetUri = targetUri; + } + + public Scope getScope() { + return Scope.SYSTEM; + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public URI getTargetUri() { + return targetUri; + } + + public List getServiceBindings() { + return Collections.unmodifiableList(bindings); + } + + public void addServiceBinding(ServiceBinding binding) { + binding.setService(this); + bindings.add(binding); + } + + public void start() { + super.start(); + for (ServiceBinding binding : bindings) { + binding.start(); + } + } + + public void stop() { + super.stop(); + for (ServiceBinding binding : bindings) { + binding.stop(); + } + } + + @Override + public boolean isSystem() { + return system; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java new file mode 100644 index 0000000000..82fb5bf62e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemCompositeBuilder.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.services.management.TuscanyManagementService; + +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; + +/** + * Produces system composite components by evaluating an assembly. + * + * @version $Rev$ $Date$ + */ +public class SystemCompositeBuilder extends AbstractCompositeBuilder { + private TuscanyManagementService managementService; + + public SystemCompositeBuilder() { + } + + public SystemCompositeBuilder(BuilderRegistry builderRegistry, + Connector connector, + TuscanyManagementService managementService) { + this.builderRegistry = builderRegistry; + this.connector = connector; + this.managementService = managementService; + } + + public CompositeComponent build(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext deploymentContext) throws BuilderException { + SystemCompositeImplementation impl = componentDefinition.getImplementation(); + CompositeComponentType componentType = impl.getComponentType(); + String name = componentDefinition.getName(); + CompositeComponent component = new CompositeComponentImpl(name, parent, connector, true); + component.setManagementService(managementService); + build(parent, component, componentType, deploymentContext); + return component; + } + + protected Class getImplementationType() { + return SystemCompositeImplementation.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java new file mode 100644 index 0000000000..952533e476 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/SystemSingletonAtomicComponent.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetDestructionException; +import org.apache.tuscany.spi.component.TargetInitializationException; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.extension.AbstractComponentExtension; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireService; + +/** + * An {@link org.apache.tuscany.spi.component.AtomicComponent} used when registering objects directly into a composite + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemSingletonAtomicComponent extends AbstractComponentExtension + implements AtomicComponent { + private T instance; + private Map inboundWires; + private WireService wireService = new JDKWireService(); + + public SystemSingletonAtomicComponent(String name, CompositeComponent parent, Class interfaze, T instance) { + super(name, parent); + this.instance = instance; + inboundWires = new HashMap(); + initWire(interfaze); + } + + + public SystemSingletonAtomicComponent(String name, + CompositeComponent parent, + List> services, + T instance) { + super(name, parent); + this.instance = instance; + inboundWires = new HashMap(); + for (Class interfaze : services) { + initWire(interfaze); + } + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + + public boolean isEagerInit() { + return false; + } + + public boolean isDestroyable() { + return false; + } + + public int getInitLevel() { + return 0; + } + + public long getMaxIdleTime() { + return -1; + } + + public long getMaxAge() { + return -1; + } + + public T getTargetInstance() throws TargetResolutionException { + return instance; + } + + public void init(Object instance) throws TargetInitializationException { + + } + + public void destroy(Object instance) throws TargetDestructionException { + + } + + public Object createInstance() throws ObjectCreationException { + throw new UnsupportedOperationException(); + } + + public void removeInstance() { + throw new UnsupportedOperationException(); + } + + public void addInboundWire(InboundWire wire) { + inboundWires.put(wire.getServiceName(), wire); + } + + public Collection getInboundWires() { + return Collections.unmodifiableCollection(inboundWires.values()); + } + + public InboundWire getInboundWire(String serviceName) { + return inboundWires.get(serviceName); + } + + public void addOutboundWire(OutboundWire wire) { + throw new UnsupportedOperationException(); + } + + public void addOutboundWires(List wires) { + throw new UnsupportedOperationException(); + } + + public Map> getOutboundWires() { + return Collections.emptyMap(); + } + + + public TargetInvoker createTargetInvoker(String targetName, Operation operation, InboundWire callbackWire) { + return null; + } + + public boolean isSystem() { + return true; + } + + private void initWire(Class interfaze) { + JavaServiceContract serviceContract = new JavaServiceContract(interfaze); + ServiceDefinition def = new ServiceDefinition(interfaze.getName(), serviceContract, false); + InboundWire wire = wireService.createWire(def); + wire.setContainer(this); + inboundWires.put(wire.getServiceName(), wire); + } + + @Override + public boolean isOptimizable() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java new file mode 100644 index 0000000000..bc087dd4c2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.ObjectFactory; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.core.wire.WireObjectFactory; + +import org.apache.tuscany.core.implementation.PojoAtomicComponent; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.injection.CallbackWireObjectFactory; +import org.apache.tuscany.core.injection.FieldInjector; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.InvalidAccessorException; +import org.apache.tuscany.core.injection.MethodInjector; + +/** + * The runtime instantiation of Java component implementations + * + * @version $Rev$ $Date$ + */ +public class JavaAtomicComponent extends PojoAtomicComponent { + + public JavaAtomicComponent(PojoConfiguration configuration) { + super(configuration); + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation, InboundWire callbackWire) { + Method[] methods; + Class callbackClass = null; + if (operation.isCallback()) { + callbackClass = operation.getServiceContract().getCallbackClass(); + methods = callbackClass.getMethods(); + + } else { + methods = operation.getServiceContract().getInterfaceClass().getMethods(); + } + Method method = findMethod(operation, methods); + return new JavaTargetInvoker(method, this, callbackWire, callbackClass, workContext, monitor); + } + + protected void onServiceWire(InboundWire wire) { + String name = wire.getCallbackReferenceName(); + if (name == null) { + // It's ok not to have one, we just do nothing + return; + } + Member member = callbackSites.get(name); + if (member != null) { + injectors.add(createCallbackInjector(member, wire.getServiceContract(), wire)); + } + } + + protected Injector createCallbackInjector(Member member, + ServiceContract contract, + InboundWire inboundWire) { + if (member instanceof Field) { + Field field = (Field) member; + ObjectFactory factory = new CallbackWireObjectFactory(field.getType(), wireService, inboundWire); + return new FieldInjector(field, factory); + } else if (member instanceof Method) { + Method method = (Method) member; + Class type = method.getParameterTypes()[0]; + ObjectFactory factory = new CallbackWireObjectFactory(type, wireService, inboundWire); + return new MethodInjector(method, factory); + } else { + throw new InvalidAccessorException("Member must be a field or method", member.getName()); + } + } + + @SuppressWarnings({"unchecked"}) + protected ObjectFactory createWireFactory(Class interfaze, OutboundWire wire) { + return new WireObjectFactory(interfaze, wire, wireService); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java new file mode 100644 index 0000000000..7d11dc9e78 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.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.core.implementation.java; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.injection.ResourceObjectFactory; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.host.ResourceHost; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.Resource; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.PropertyValue; + +/** + * Builds a Java-based atomic context from a component definition + * + * @version $$Rev$$ $$Date$$ + */ +public class JavaComponentBuilder extends ComponentBuilderExtension { + + private ResourceHost host; + + @Autowire + public void setHost(ResourceHost host) { + this.host = host; + } + + @SuppressWarnings("unchecked") + public AtomicComponent build(CompositeComponent parent, + ComponentDefinition definition, + DeploymentContext deployment) throws BuilderConfigException { + PojoComponentType> componentType = + definition.getImplementation().getComponentType(); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setParent(parent); + if (definition.getInitLevel() != null) { + configuration.setInitLevel(definition.getInitLevel()); + } else { + configuration.setInitLevel(componentType.getInitLevel()); + } + if (componentType.getMaxAge() > 0) { + configuration.setMaxAge(componentType.getMaxAge()); + } else if (componentType.getMaxIdleTime() > 0) { + configuration.setMaxIdleTime(componentType.getMaxIdleTime()); + } + Method initMethod = componentType.getInitMethod(); + if (initMethod != null) { + configuration.setInitInvoker(new MethodEventInvoker(initMethod)); + } + Method destroyMethod = componentType.getDestroyMethod(); + if (destroyMethod != null) { + configuration.setDestroyInvoker(new MethodEventInvoker(destroyMethod)); + } + + configuration.setWireService(wireService); + configuration.setWorkContext(workContext); + configuration.setScheduler(workScheduler); + configuration.setImplementationClass(definition.getImplementation().getImplementationClass()); + + // setup property injection sites + for (JavaMappedProperty property : componentType.getProperties().values()) { + configuration.addPropertySite(property.getName(), property.getMember()); + } + + // setup reference injection sites + try { + + for (JavaMappedReference reference : componentType.getReferences().values()) { + Member member = reference.getMember(); + if (member != null) { + // could be null if the reference is mapped to a constructor + configuration.addReferenceSite(reference.getName(), member); + } + } + } catch ( Exception e ) { + e.printStackTrace(); + } + + for (Resource resource : componentType.getResources().values()) { + Member member = resource.getMember(); + if (member != null) { + // could be null if the resource is mapped to a constructor + configuration.addResourceSite(resource.getName(), member); + } + } + + // setup constructor injection + ConstructorDefinition ctorDef = componentType.getConstructorDefinition(); + Constructor constr = ctorDef.getConstructor(); + PojoObjectFactory instanceFactory = new PojoObjectFactory(constr); + configuration.setInstanceFactory(instanceFactory); + configuration.getConstructorParamNames().addAll(ctorDef.getInjectionNames()); + for (Class clazz : constr.getParameterTypes()) { + configuration.addConstructorParamType(clazz); + } + configuration.setMonitor(monitor); + configuration.setName(definition.getName()); + JavaAtomicComponent component = new JavaAtomicComponent(configuration); + + // handle properties + handleProperties(definition, component); + + // handle resources + handleResources(componentType, component, parent); + + handleCallbackSites(componentType, configuration); + + // FIXME JFM this should be refactored to be by operation + // as per the Java C&I @AllowsPassByReference can be at the class level (applying to all methods in + //...the class or at the method level applying only to the specific method + component.setAllowsPassByReference(componentType.isAllowsPassByReference()); + component.setPassByReferenceMethods(componentType.getPassByReferenceMethods()); + + if (componentType.getConversationIDMember() != null) { + component.addConversationIDFactory(componentType.getConversationIDMember()); + } + + return component; + } + + private void handleCallbackSites(ComponentType componentType, PojoConfiguration configuration) { + for (Object sd : componentType.getServices().values()) { + // TODO: TUSCANY-1111, if using componentType side file with wsdl idl then may not get JavaMappedService + if (sd instanceof JavaMappedService) { + JavaMappedService service = (JavaMappedService) sd; + // setup callback injection sites + if (service.getCallbackReferenceName() != null) { + // Only if there is a callback reference in the service + configuration.addCallbackSite(service.getCallbackReferenceName(), service.getCallbackMember()); + } + } + } + } + + @SuppressWarnings({"unchecked"}) + private void handleResources( + PojoComponentType> componentType, + JavaAtomicComponent component, + CompositeComponent parent) { + for (Resource resource : componentType.getResources().values()) { + ObjectFactory objectFactory = resource.getObjectFactory(); + if (objectFactory != null) { + component.addResourceFactory(resource.getName(), objectFactory); + } else { + String name = resource.getName(); + boolean optional = resource.isOptional(); + Class type = (Class) resource.getType(); + ResourceObjectFactory factory; + String mappedName = resource.getMappedName(); + if (mappedName == null) { + // by type + factory = new ResourceObjectFactory(type, optional, parent, host); + } else { + factory = new ResourceObjectFactory(type, mappedName, optional, parent, host); + } + component.addResourceFactory(name, factory); + } + } + } + + private void handleProperties(ComponentDefinition definition, JavaAtomicComponent component) { + for (PropertyValue property : definition.getPropertyValues().values()) { + ObjectFactory factory = property.getValueFactory(); + if (factory != null) { + component.addPropertyFactory(property.getName(), factory); + } + } + } + + protected Class getImplementationType() { + return JavaImplementation.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java new file mode 100644 index 0000000000..6eaba3bf2f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.io.File; +import java.io.FileOutputStream; +import java.net.URI; +import java.net.URL; +import java.util.Iterator; + +import org.apache.tuscany.core.util.JavaIntrospectionHelper; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ComponentTypeReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.osoa.sca.annotations.Constructor; + +/** + * @version $Rev$ $Date$ + */ +public class JavaComponentTypeLoader extends ComponentTypeLoaderExtension { + @Autowire + protected JavaInterfaceProcessorRegistry processorRegistry; + + private Introspector introspector; + + @Constructor( {"registry", "introspector"}) + public JavaComponentTypeLoader(@Autowire + LoaderRegistry loaderRegistry, @Autowire + IntrospectionRegistry introspector) { + super(loaderRegistry); + this.introspector = introspector; + } + + @Override + protected Class getImplementationClass() { + return JavaImplementation.class; + } + + public void load(CompositeComponent parent, JavaImplementation implementation, DeploymentContext deploymentContext) + throws LoaderException { + Class implClass = implementation.getImplementationClass(); + PojoComponentType> componentType = loadByIntrospection(parent, implementation, deploymentContext); + URL resource = implClass.getResource(JavaIntrospectionHelper.getBaseName(implClass) + ".componentType"); + if (resource != null) { + // TODO: TUSCANY-1111, How to merge the component type loaded from the file into the PojoComponentType + PojoComponentType sideFileCT = loadFromSidefile(parent, resource, deploymentContext); + + // TODO: TUSCANY-1111, hack to get the sidefile defined WSDLServiceContract used + // only works with a single service + Iterator it = componentType.getServices().values().iterator(); + for (Object o : sideFileCT.getServices().values()) { + ServiceDefinition sideFileSD = (ServiceDefinition)o; + ServiceDefinition actualSD = (ServiceDefinition)it.next(); + ServiceContract newServiceContract = sideFileSD.getServiceContract(); + ServiceContract contract = actualSD.getServiceContract(); + if (JavaServiceContract.class.isInstance(contract)) { + try { + // [rfeng] AS we now defer the java interface processing for TUSCANY-1165 + // We need to do the full introspection now + contract = + processorRegistry.introspect(contract.getInterfaceClass(), + contract.getCallbackClass(), + true); + } catch (InvalidServiceContractException e) { + throw new LoaderException(e); + } + } + // TODO: TUSCANY-1111, runtime requires interfaceClass + // but currently there's no way of gen'ing that from WSDL + newServiceContract.setInterfaceClass(contract.getInterfaceClass()); + newServiceContract.setDataBinding(contract.getDataBinding()); + actualSD.setServiceContract(newServiceContract); + } + + //TODO: if introspection has not yeilded any info, then atleast pick up things in the sidefile + //[svkrish] needed this for references overriding verification + ComponentTypeReferenceDefinition ctRefSideFile = null; + for (ComponentTypeReferenceDefinition ctRefIntrospection : componentType.getReferences().values()) { + if(ctRefIntrospection.getTargets() == null | ctRefIntrospection.getTargets().size() == 0) { + ctRefSideFile = sideFileCT.getReferences().get(ctRefIntrospection.getName()); + if (ctRefSideFile != null) { + for(URI uri : ctRefSideFile.getTargets()) { + ctRefIntrospection.addTarget(uri); + } + } + } + } + } + implementation.setComponentType(componentType); + } + + protected PojoComponentType loadByIntrospection(CompositeComponent parent, + JavaImplementation implementation, + DeploymentContext deploymentContext) throws ProcessingException { + PojoComponentType> componentType = + new PojoComponentType>(); + Class implClass = implementation.getImplementationClass(); + introspector.introspect(parent, implClass, componentType, deploymentContext); + return componentType; + } + + protected PojoComponentType loadFromSidefile(CompositeComponent parent, URL url, DeploymentContext deploymentContext) + throws LoaderException { + PojoComponentType> componentType = + new PojoComponentType>(); + return loaderRegistry.load(parent, componentType, url, PojoComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java new file mode 100644 index 0000000000..432bf31d63 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import org.apache.tuscany.spi.model.AtomicImplementation; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class JavaImplementation extends AtomicImplementation { + private String className; + private Class implementationClass; + + public JavaImplementation() { + } + + public JavaImplementation(Class implementationClass) { + this.implementationClass = implementationClass; + this.className = implementationClass.getName(); + } + + public JavaImplementation(Class implementationClass, PojoComponentType componentType) { + super(componentType); + this.implementationClass = implementationClass; + this.className = implementationClass == null ? null : implementationClass.getName(); + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + this.implementationClass = null; + } + + public Class getImplementationClass() { + return implementationClass; + } + + public void setImplementationClass(Class implementationClass) { + this.implementationClass = implementationClass; + this.className = implementationClass.getName(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java new file mode 100644 index 0000000000..0f458c7ab4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.annotation.Autowire; + +public class JavaImplementationLoader extends LoaderExtension { + public static final QName IMPLEMENTATION_JAVA = new QName(SCA_NS, "implementation.java"); + + @Constructor({"registry"}) + public JavaImplementationLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + @Override + public QName getXMLType() { + return IMPLEMENTATION_JAVA; + } + + public ModelObject load(CompositeComponent parent, ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + assert IMPLEMENTATION_JAVA.equals(reader.getName()); + String implClass = reader.getAttributeValue(null, "class"); + Class implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader()); + + JavaImplementation implementation = new JavaImplementation(); + implementation.setClassName(implClass); + implementation.setImplementationClass(implementationClass); + registry.loadComponentType(parent, implementation, deploymentContext); + LoaderUtil.skipToEndElement(reader); + return implementation; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java new file mode 100644 index 0000000000..6da60304fa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; + +import org.osoa.sca.NoRegisteredCallbackException; + +import org.apache.tuscany.spi.component.ComponentException; +import org.apache.tuscany.spi.component.InvalidConversationSequenceException; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.extension.ExecutionMonitor; +import org.apache.tuscany.spi.extension.TargetInvokerExtension; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.InboundWire; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.findClosestMatchingMethod; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods; + +/** + * Responsible for synchronously dispatching an invocation to a Java component implementation instance + * + * @version $Rev$ $Date$ + */ +public class JavaTargetInvoker extends TargetInvokerExtension { + protected Method operation; + protected JavaAtomicComponent component; + protected Object target; + protected Class callbackClass; + protected boolean stateless; + + public JavaTargetInvoker(Method operation, + JavaAtomicComponent component, + InboundWire wire, + Class callbackClass, + WorkContext context, + ExecutionMonitor monitor) { + super(wire, context, monitor); + assert operation != null : "Operation method cannot be null"; + this.operation = operation; + this.component = component; + stateless = Scope.STATELESS == component.getScope(); + this.callbackClass = callbackClass; + } + + public JavaTargetInvoker(Method operation, + JavaAtomicComponent component, + InboundWire callbackWire, + WorkContext context, + ExecutionMonitor monitor) { + this(operation, component, callbackWire, null, context, monitor); + } + + public Object invokeTarget(final Object payload, final short sequence) throws InvocationTargetException { + try { + Object instance = getInstance(sequence); + if (callbackClass != null && !callbackClass.isInstance(instance)) { + throw new InvocationTargetException( + new NoRegisteredCallbackException("Instance is does not implement callback [" + + callbackClass.toString() + "]")); + } + if (!operation.getDeclaringClass().isInstance(instance)) { + Set methods = getAllUniquePublicProtectedMethods(instance.getClass()); + Method newOperation = findClosestMatchingMethod(operation.getName(), + operation.getParameterTypes(), methods); + if (newOperation != null) { + operation = newOperation; + } + } + Object ret; + if (payload != null && !payload.getClass().isArray()) { + ret = operation.invoke(instance, payload); + } else { + ret = operation.invoke(instance, (Object[]) payload); + } + if (stateless) { + // notify a stateless instance of a destruction event after the invoke + component.destroy(instance); + } else if (sequence == END) { + component.destroy(instance); + // if end conversation, remove resource + component.removeInstance(); + } + return ret; + } catch (IllegalAccessException e) { + throw new InvocationTargetException(e); + } catch (ComponentException e) { + throw new InvocationTargetException(e); + } + } + + @Override + public JavaTargetInvoker clone() throws CloneNotSupportedException { + try { + JavaTargetInvoker invoker = (JavaTargetInvoker) super.clone(); + invoker.target = null; + return invoker; + } catch (CloneNotSupportedException e) { + return null; // will not happen + } + } + + /** + * Resolves the target service instance or returns a cached one + */ + protected Object getInstance(short sequence) throws TargetException { + if (!cacheable) { + if (sequence == START || sequence == NONE) { + return component.getTargetInstance(); + } else if (sequence == CONTINUE || sequence == END) { + return component.getAssociatedTargetInstance(); + } else { + throw new InvalidConversationSequenceException("Unknown sequence type", String.valueOf(sequence)); + } + } else { + assert sequence == NONE; // conversations are not cacheable + if (target == null) { + target = component.getTargetInstance(); + } + return target; + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java new file mode 100644 index 0000000000..19244810fd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AllowsPassByReferenceProcessor.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; + +import org.osoa.sca.annotations.AllowsPassByReference; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Processes {@link AllowsPassByReference} on an implementation + * + * @version $Rev: 479093 $ $Date: 2006-11-25 12:34:41 +0530 (Sat, 25 Nov 2006) $ + */ +public class AllowsPassByReferenceProcessor extends ImplementationProcessorExtension { + + public void visitClass(CompositeComponent parent, + Class clazz, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + AllowsPassByReference annotation = clazz.getAnnotation(AllowsPassByReference.class); + if (annotation != null) { + type.setAllowsPassByReference(true); + } else { + type.setAllowsPassByReference(false); + } + + } + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType> type, + DeploymentContext context)throws ProcessingException { + + AllowsPassByReference annotation = method.getAnnotation(AllowsPassByReference.class); + if (annotation != null) { + type.getPassByReferenceMethods().add(method.getName()); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java new file mode 100644 index 0000000000..03d092880d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when constructor parameters cannot be unambiguously resolved to a property or reference + * + * @version $Rev$ $Date$ + */ +public class AmbiguousConstructorException extends ProcessingException { + + public AmbiguousConstructorException(String message) { + super(message); + } + + public AmbiguousConstructorException(String message, String identifier) { + super(message, identifier); + } + + public AmbiguousConstructorException(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java new file mode 100644 index 0000000000..50f60147ee --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + + +/** + * Handles processing of a constructor decorated with {@link org.osoa.sca.annotations.Constructor} + * + * @version $Rev$ $Date$ + */ +@SuppressWarnings("unchecked") +public class ConstructorProcessor extends ImplementationProcessorExtension { + + private ImplementationProcessorService service; + + public ConstructorProcessor(@Autowire ImplementationProcessorService service) { + this.service = service; + } + + public void visitClass(CompositeComponent parent, Class clazz, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + Constructor[] ctors = clazz.getConstructors(); + boolean found = false; + for (Constructor constructor : ctors) { + if (constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) { + if (found) { + String name = constructor.getDeclaringClass().getName(); + throw new DuplicateConstructorException("Multiple constructors marked with @Constructor", name); + } + found = true; + } + } + } + + public void visitConstructor(CompositeComponent parent, Constructor constructor, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + org.osoa.sca.annotations.Constructor annotation = + constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class); + if (annotation == null) { + return; + } + ConstructorDefinition definition = type.getConstructorDefinition(); + if (definition != null && !definition.getConstructor().equals(constructor)) { + String name = constructor.getDeclaringClass().getName(); + throw new DuplicateConstructorException("Multiple constructor definitions found", name); + } else if (definition == null) { + definition = new ConstructorDefinition(constructor); + } + Class[] params = constructor.getParameterTypes(); + String[] names = annotation.value(); + Annotation[][] annotations = constructor.getParameterAnnotations(); + List injectionNames = definition.getInjectionNames(); + for (int i = 0; i < params.length; i++) { + Class param = params[i]; + Annotation[] paramAnnotations = annotations[i]; + try { + if (!service.processParam(param, + constructor.getGenericParameterTypes()[i], + paramAnnotations, + names, + i, + type, + injectionNames)) { + String name = (i < names.length) ? names[i] : ""; + service.addName(injectionNames, i, name); + } + } catch (ProcessingException e) { + e.setMember(constructor); + throw e; + } + } + if (names.length != 0 && names[0].length() != 0 && names.length != params.length) { + throw new InvalidConstructorException("Names in @Constructor do not match number of parameters"); + } + type.setConstructorDefinition(definition); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java new file mode 100644 index 0000000000..c207fdb5c4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.osoa.sca.CompositeContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.ComponentContext; +import org.osoa.sca.annotations.Context; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.implementation.java.Resource; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.injection.CompositeContextObjectFactory; +import org.apache.tuscany.core.injection.RequestContextObjectFactory; +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * Processes {@link @Context} annotations on a component implementation and adds a {@link JavaMappedProperty} to the + * component type which will be used to inject the appropriate context + * + * @version $Rev$ $Date$ + */ +public class ContextProcessor extends ImplementationProcessorExtension { + private WireService wireService; + private WorkContext workContext; + + @Autowire + public void setWireService(WireService wireService) { + this.wireService = wireService; + } + + @Autowire + public void setWorkContext(WorkContext workContext) { + this.workContext = workContext; + } + + public void visitMethod(CompositeComponent parent, + Method method, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + if (method.getAnnotation(Context.class) == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalContextException("Context setter must have one parameter", method.toString()); + } + Class paramType = method.getParameterTypes()[0]; + if (ComponentContext.class.equals(paramType)) { + // FIXME: handle injection of ComponentContext + throw new UnsupportedOperationException(); +/* + String name = method.getName(); + name = JavaIntrospectionHelper.toPropertyName(name); + Resource resource = new Resource(); + resource.setName(name); + resource.setMember(method); + resource.setObjectFactory(new CompositeContextObjectFactory(parent, wireService)); + type.getResources().put(name, resource); +*/ + } else if (RequestContext.class.equals(paramType)) { + String name = method.getName(); + name = JavaIntrospectionHelper.toPropertyName(name); + Resource resource = new Resource(); + resource.setName(name); + resource.setMember(method); + resource.setObjectFactory(new RequestContextObjectFactory(workContext)); + type.getResources().put(name, resource); + } else { + throw new UnknownContextTypeException(paramType.getName()); + } + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + if (field.getAnnotation(Context.class) == null) { + return; + } + Class paramType = field.getType(); + if (ComponentContext.class.equals(paramType)) { + // FIXME: handle injection of ComponentContext + throw new UnsupportedOperationException(); +/* + String name = field.getName(); + Resource resource = new Resource(); + resource.setName(name); + resource.setMember(field); + resource.setObjectFactory(new CompositeContextObjectFactory(parent, wireService)); + type.getResources().put(name, resource); +*/ + } else if (CompositeContext.class.equals(paramType)) { + String name = field.getName(); + Resource resource = new Resource(); + resource.setName(name); + resource.setMember(field); + resource.setObjectFactory(new CompositeContextObjectFactory(parent, wireService)); + type.getResources().put(name, resource); + } else if (RequestContext.class.equals(paramType)) { + String name = field.getName(); + name = JavaIntrospectionHelper.toPropertyName(name); + Resource resource = new Resource(); + resource.setName(name); + resource.setMember(field); + resource.setObjectFactory(new RequestContextObjectFactory(workContext)); + type.getResources().put(name, resource); + } else { + throw new UnknownContextTypeException(paramType.getName()); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java new file mode 100644 index 0000000000..fa369f72c6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConversationProcessor.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.osoa.sca.annotations.ConversationAttributes; +import org.osoa.sca.annotations.ConversationID; +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +public class ConversationProcessor extends ImplementationProcessorExtension { + private static final String SECONDS = " SECONDS"; + private static final String MINUTES = " MINUTES"; + private static final String HOURS = " HOURS"; + private static final String DAYS = " DAYS"; + private static final String YEARS = " YEARS"; + + public void visitClass(CompositeComponent parent, + Class clazz, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + + ConversationAttributes conversation = clazz.getAnnotation(ConversationAttributes.class); + if (conversation == null) { + return; + } + Scope scope = clazz.getAnnotation(Scope.class); + if (scope == null) { + // implicitly assume conversation + type.setImplementationScope(org.apache.tuscany.spi.model.Scope.CONVERSATION); + } else if (scope != null && !"CONVERSATION".equals(scope.value().toUpperCase())) { + throw new InvalidConversationalImplementation( + "Service is marked with @ConversationAttributes but the scope is not @Scope(\"CONVERSATION\")", + clazz.getName()); + } else if (conversation != null) { + long maxAge; + long maxIdleTime; + String maxAgeVal = conversation.maxAge(); + String maxIdleTimeVal = conversation.maxIdleTime(); + if (maxAgeVal.length() > 0 && maxIdleTimeVal.length() > 0) { + throw new InvalidConversationalImplementation("Max idle time and age both specified", clazz.getName()); + } + try { + if (maxAgeVal.length() > 0) { + maxAge = convertTimeMillis(maxAgeVal); + type.setMaxAge(maxAge); + } + } catch (NumberFormatException e) { + throw new InvalidConversationalImplementation("Invalid maximum age", clazz.getName(), e); + } + try { + if (maxIdleTimeVal.length() > 0) { + maxIdleTime = convertTimeMillis(maxIdleTimeVal); + type.setMaxIdleTime(maxIdleTime); + } + } catch (NumberFormatException e) { + throw new InvalidConversationalImplementation("Invalid maximum idle time", clazz.getName(), e); + } + } + + } + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + ConversationID conversationID = method.getAnnotation(ConversationID.class); + if (conversationID == null) { + return; + } + type.setConversationIDMember(method); + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + ConversationID conversationID = field.getAnnotation(ConversationID.class); + if (conversationID == null) { + return; + } + type.setConversationIDMember(field); + } + + protected long convertTimeMillis(String expr) throws NumberFormatException { + expr = expr.trim().toUpperCase(); + int i = expr.lastIndexOf(SECONDS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 1000; + } + i = expr.lastIndexOf(MINUTES); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 60000; + } + + i = expr.lastIndexOf(HOURS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 3600000; + } + i = expr.lastIndexOf(DAYS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 86400000; + } + i = expr.lastIndexOf(YEARS); + if (i >= 0) { + String units = expr.substring(0, i); + return Long.parseLong(units) * 31556926000L; + } + return Long.parseLong(expr) * 1000; // assume seconds if no suffix specified + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java new file mode 100644 index 0000000000..7ef540432f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.osoa.sca.annotations.Destroy; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Processes the {@link @Destroy} annotation on a component implementation and updates the component type with the + * decorated destructor method + * + * @version $Rev$ $Date$ + */ +public class DestroyProcessor extends ImplementationProcessorExtension { + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + Destroy annotation = method.getAnnotation(Destroy.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 0) { + throw new IllegalDestructorException("Destructor must not have argments", method.toString()); + } + if (type.getDestroyMethod() != null) { + throw new DuplicateDestructorException("More than one destructor found on implementation"); + } + if (Modifier.isProtected(method.getModifiers())) { + method.setAccessible(true); + } + type.setDestroyMethod(method); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java new file mode 100644 index 0000000000..88db7ebb79 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when more than one component implementation constructor is annotated with {@link + * org.osoa.sca.annotations.Constructor} + * + * @version $Rev$ $Date$ + */ +public class DuplicateConstructorException extends ProcessingException { + + public DuplicateConstructorException(String message) { + super(message); + } + + public DuplicateConstructorException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java new file mode 100644 index 0000000000..6225bd6219 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation is annotated multiple times with {@link org.osoa.sca.annotations.Destroy} + * + * @version $Rev$ $Date$ + */ +public class DuplicateDestructorException extends ProcessingException { + + public DuplicateDestructorException(String message) { + super(message); + } + + public DuplicateDestructorException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java new file mode 100644 index 0000000000..105edee1a2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation is annotated multiple times with {@link @org.osoa.sca.annotations.Init} + * + * @version $Rev$ $Date$ + */ +public class DuplicateInitException extends ProcessingException { + + public DuplicateInitException(String message) { + super(message); + } + + public DuplicateInitException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java new file mode 100644 index 0000000000..5eae1461c2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation has more than one reference injection site with the same name + * + * @version $Rev$ $Date$ + */ +public class DuplicateReferenceException extends ProcessingException { + + public DuplicateReferenceException(String message) { + super(message); + } + + + public DuplicateReferenceException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java new file mode 100644 index 0000000000..9dd718c03e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateResourceException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation has more than one resource injection site with the same name + * + * @version $Rev$ $Date$ + */ +public class DuplicateResourceException extends ProcessingException { + + public DuplicateResourceException(String message) { + super(message); + } + + public DuplicateResourceException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java new file mode 100644 index 0000000000..a2431dc5b1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/EagerInitProcessor.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Handles processing of {@link org.osoa.sca.annotations.EagerInit} + * + * @version $Rev$ $Date$ + */ +public class EagerInitProcessor extends ImplementationProcessorExtension { + + public void visitClass(CompositeComponent parent, Class clazz, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + super.visitClass(parent, clazz, type, context); + EagerInit annotation = clazz.getAnnotation(EagerInit.class); + if (annotation == null) { + Class superClass = clazz.getSuperclass(); + while (!Object.class.equals(superClass)) { + annotation = superClass.getAnnotation(EagerInit.class); + if (annotation != null) { + break; + } + superClass = superClass.getSuperclass(); + } + if (annotation == null) { + return; + } + } + type.setInitLevel(50); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java new file mode 100644 index 0000000000..e00c96664b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java @@ -0,0 +1,550 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllInterfaces; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllPublicAndProtectedFields; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.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 inteface is annotated, need to calculate a single service comprising all public methods that are not + * reference or property injection sites. If that service can be exactly mapped to an interface implemented by the class + * then the service interface will be defined in terms of that interface. + * + * @version $Rev$ $Date$ + */ +public class HeuristicPojoProcessor extends ImplementationProcessorExtension { + private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension(); + private ImplementationProcessorService implService; + + public HeuristicPojoProcessor(@Autowire ImplementationProcessorService service) { + this.implService = service; + } + + public void visitEnd( + CompositeComponent parent, + Class clazz, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + Map services = type.getServices(); + if (services.isEmpty()) { + // heuristically determine the service + // TODO finish algorithm + Set interfaces = getAllInterfaces(clazz); + if (interfaces.size() == 0) { + // class is the interface + JavaMappedService service; + try { + service = implService.createService(clazz); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } else if (interfaces.size() == 1) { + JavaMappedService service; + try { + service = implService.createService(interfaces.iterator().next()); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + Set methods = getAllUniquePublicProtectedMethods(clazz); + if (!type.getReferences().isEmpty() || !type.getProperties().isEmpty()) { + // references and properties have been explicitly defined + if (type.getServices().isEmpty()) { + calculateServiceInterface(clazz, type, methods); + if (type.getServices().isEmpty()) { + throw new ServiceTypeNotFoundException(clazz.getName()); + } + } + evaluateConstructor(type, clazz); + return; + } + calcPropRefs(methods, services, type, clazz); + evaluateConstructor(type, clazz); + } + + private void calcPropRefs(Set methods, + Map services, + PojoComponentType> type, + Class clazz) throws ProcessingException { + // heuristically determine the properties references + // make a first pass through all public methods with one param + for (Method method : methods) { + if (method.getParameterTypes().length != 1 || !Modifier.isPublic(method.getModifiers()) + || !method.getName().startsWith("set") + || method.getReturnType() != void.class) { + continue; + } + if (!isInServiceInterface(method, services)) { + String name = toPropertyName(method.getName()); + // avoid duplicate property or ref names + if (!type.getProperties().containsKey(name) && !type.getReferences().containsKey(name)) { + Class param = method.getParameterTypes()[0]; + Type genericType = method.getGenericParameterTypes()[0]; + if (isReferenceType(genericType)) { + type.add(createReference(name, method, param)); + } else { + type.add(createProperty(name, method, param)); + } + } + } + } + // second pass for protected methods with one param + for (Method method : methods) { + if (method.getParameterTypes().length != 1 || !Modifier.isProtected(method.getModifiers()) + || !method.getName().startsWith("set") + || method.getReturnType() != void.class) { + continue; + } + Class param = method.getParameterTypes()[0]; + String name = toPropertyName(method.getName()); + // avoid duplicate property or ref names + if (!type.getProperties().containsKey(name) && !type.getReferences().containsKey(name)) { + if (isReferenceType(param)) { + type.add(createReference(name, method, param)); + } else { + type.add(createProperty(name, method, param)); + } + } + } + Set fields = getAllPublicAndProtectedFields(clazz); + for (Field field : fields) { + Class paramType = field.getType(); + if (isReferenceType(paramType)) { + type.add(createReference(field.getName(), field, paramType)); + } else { + type.add(createProperty(field.getName(), field, paramType)); + } + } + } + + /** + * Determines the constructor to use based on the component type's references and properties + * + * @param type the component type + * @param clazz the implementation class corresponding to the component type + * @throws NoConstructorException if no suitable constructor is found + * @throws AmbiguousConstructorException if the parameters of a constructor cannot be unambiguously mapped to + * references and properties + */ + @SuppressWarnings("unchecked") + private void evaluateConstructor( + PojoComponentType> type, + Class clazz) throws ProcessingException { + // determine constructor if one is not annotated + ConstructorDefinition definition = type.getConstructorDefinition(); + Constructor constructor; + boolean explict = false; + if (definition != null + && definition.getConstructor().getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) { + // the constructor was already defined explicitly + return; + } else if (definition != null) { + explict = true; + constructor = definition.getConstructor(); + } else { + // no definition, heuristically determine constructor + Constructor[] constructors = clazz.getConstructors(); + if (constructors.length == 0) { + throw new NoConstructorException("No public constructor for class", clazz.getName()); + } else if (constructors.length == 1) { + constructor = constructors[0]; + } else { + // FIXME multiple constructors, none yet done + Constructor selected = null; + int sites = type.getProperties().size() + type.getReferences().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 = new ConstructorDefinition(selected); + type.setConstructorDefinition(definition); + // return; + } + definition = new ConstructorDefinition(constructor); + type.setConstructorDefinition(definition); + } + Class[] params = constructor.getParameterTypes(); + if (params.length == 0) { + return; + } + List paramNames = definition.getInjectionNames(); + Map> props = type.getProperties(); + Map refs = type.getReferences(); + Annotation[][] annotations = constructor.getParameterAnnotations(); + if (!explict) { + // the constructor wasn't defined by an annotation, so check to see if any of the params have an annotation + // which we can impute as explicitly defining the constructor, e.g. @Property, @Reference, or @Autowire + explict = implService.injectionAnnotationsPresent(annotations); + } + if (explict) { + for (int i = 0; i < params.length; i++) { + Class param = params[i]; + implService.processParam(param, + constructor.getGenericParameterTypes()[i], + annotations[i], + new String[0], + i, + type, + paramNames); + } + } else { + if (!implService.areUnique(params)) { + throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor"); + } + if (!calcPropRefUniqueness(props.values(), refs.values())) { + throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor"); + } + boolean empty = props.size() + refs.size() == 0; + if (!empty) { + calcParamNames(params, props, refs, paramNames); + } else { + heuristicParamNames(params, refs, props, paramNames); + + } + } + } + + private void calcParamNames(Class[] params, + Map> props, + Map refs, + List paramNames) + throws AmbiguousConstructorException { + // the constructor param types must unambiguously match defined reference or property types + for (Class param : params) { + String name = findReferenceOrProperty(param, props, refs); + if (name == null) { + throw new AmbiguousConstructorException(param.getName()); + } + paramNames.add(name); + } + } + + private void heuristicParamNames(Class[] params, + Map refs, + Map> props, + List paramNames) + throws ProcessingException { + // heuristically determine refs and props from the parameter types + for (Class param : params) { + String name = getBaseName(param).toLowerCase(); + if (isReferenceType(param)) { + refs.put(name, createReference(name, null, param)); + } else { + props.put(name, createProperty(name, null, param)); + } + paramNames.add(name); + } + } + + /** + * Returns true if the union of the given collections of properties and references have unique Java types + */ + private boolean calcPropRefUniqueness( + Collection> props, + Collection refs) { + + Class[] classes = new Class[props.size() + refs.size()]; + int i = 0; + for (JavaMappedProperty property : props) { + classes[i] = property.getJavaType(); + i++; + } + for (JavaMappedReference reference : refs) { + classes[i] = reference.getServiceContract().getInterfaceClass(); + i++; + } + return implService.areUnique(classes); + } + + /** + * Unambiguously finds the reference or property associated with the given type + * + * @return the name of the reference or property if found, null if not + * @throws AmbiguousConstructorException if the constructor parameter cannot be resolved to a property or reference + */ + private String findReferenceOrProperty( + Class type, + Map> props, + Map refs) throws AmbiguousConstructorException { + + String name = null; + for (JavaMappedProperty property : props.values()) { + if (property.getJavaType().equals(type)) { + if (name != null) { + throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type", + type.getName()); + } + name = property.getName(); + // do not break since ambiguities must be checked, i.e. more than one prop or ref of the same type + } + } + for (JavaMappedReference reference : refs.values()) { + if (reference.getServiceContract().getInterfaceClass().equals(type)) { + if (name != null) { + throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type", + type.getName()); + } + name = reference.getName(); + // do not break since ambiguities must be checked, i.e. more than one prop or ref of the same type + } + } + return name; + } + + /** + * Returns true if a given type is reference according to the SCA specification rules for determining reference + * types + */ + private boolean isReferenceType(Type operationType) { + Class rawType; + Class referenceType = null; + if (operationType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) operationType; + rawType = (Class) parameterizedType.getRawType(); + Type[] typeArgs = parameterizedType.getActualTypeArguments(); + if (typeArgs.length == 1) { + referenceType = (Class) typeArgs[0]; + } + } else { + rawType = (Class) operationType; + } + if (rawType.isArray()) { + referenceType = rawType.getComponentType(); + } else if (Collection.class.isAssignableFrom(rawType) && referenceType == null) { + return true; + } + if (referenceType != null) { + return referenceType.getAnnotation(Remotable.class) != null + || referenceType.getAnnotation(Service.class) != null; + } else { + return rawType.getAnnotation(Remotable.class) != null || rawType.getAnnotation(Service.class) != null; + } + } + + /** + * Returns true if the given operation is defined in the collection of service interfaces + */ + private boolean isInServiceInterface(Method operation, Map services) { + for (JavaMappedService service : services.values()) { + Class clazz = service.getServiceContract().getInterfaceClass(); + if (operation.getDeclaringClass().equals(clazz)) { + return true; + } + Method[] methods = service.getServiceContract().getInterfaceClass().getMethods(); + for (Method method : methods) { + if (operation.getName().equals(method.getName()) + && operation.getParameterTypes().length == method.getParameterTypes().length) { + Class[] methodTypes = method.getParameterTypes(); + for (int i = 0; i < operation.getParameterTypes().length; i++) { + Class paramType = operation.getParameterTypes()[i]; + if (!paramType.equals(methodTypes[i])) { + break; + } else if (i == operation.getParameterTypes().length - 1) { + return true; + } + } + } + } + } + return false; + } + + /** + * Creates a mapped reference + * + * @param name the reference name + * @param member the injection site the reference maps to + * @param paramType the service interface of the reference + */ + private JavaMappedReference createReference(String name, Member member, Class paramType) + throws ProcessingException { + return implService.createReference(name, member, paramType); + } + + /** + * Creates a mapped property + * + * @param name the property name + * @param member the injection site the reference maps to + * @param paramType the property type + */ + private JavaMappedProperty createProperty(String name, Member member, Class paramType) { + JavaMappedProperty property = new JavaMappedProperty(); + property.setName(name); + property.setMember(member); + property.setMustSupply(false); + property.setJavaType(paramType); + TypeInfo xmlType = typeMapper.getXMLType(paramType); + if (xmlType != null) { + property.setXmlType(xmlType.getQName()); + } + + return property; + } + + /** + * Populates a component type with a service whose interface type is determined by examining all implemented + * interfaces of the given class and chosing one whose operations match all of the class's non-property and + * non-reference methods + * + * @param clazz the class to examine + * @param type the component type + * @param methods all methods in the class to examine + */ + private void calculateServiceInterface( + Class clazz, + PojoComponentType> type, + Set methods) throws ProcessingException { + List nonPropRefMethods = new ArrayList(); + // Map services = type.getServices(); + Map references = type.getReferences(); + Map> properties = type.getProperties(); + // calculate methods that are not properties or references + for (Method method : methods) { + String name = toPropertyName(method.getName()); + if (!references.containsKey(name) && !properties.containsKey(name)) { + nonPropRefMethods.add(method); + } + } + // determine if an implemented interface matches all of the non-property and non-reference methods + Class[] interfaces = clazz.getInterfaces(); + if (interfaces.length == 0) { + return; + } + for (Class interfaze : interfaces) { + if (analyzeInterface(interfaze, nonPropRefMethods)) { + JavaMappedService service; + try { + service = implService.createService(interfaze); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + } + + /** + * Determines if the methods of a given interface match the given list of methods + * + * @param interfaze the interface to examine + * @param nonPropRefMethods the list of methods to match against + * @return true if the interface matches + */ + private boolean analyzeInterface(Class interfaze, List nonPropRefMethods) { + Method[] interfaceMethods = interfaze.getMethods(); + if (nonPropRefMethods.size() != interfaceMethods.length) { + return false; + } + for (Method method : nonPropRefMethods) { + boolean found = false; + for (Method interfaceMethod : interfaceMethods) { + if (interfaceMethod.getName().equals(method.getName())) { + Class[] interfaceParamTypes = interfaceMethod.getParameterTypes(); + Class[] methodParamTypes = method.getParameterTypes(); + if (interfaceParamTypes.length == methodParamTypes.length) { + if (interfaceParamTypes.length == 0) { + found = true; + } else { + for (int i = 0; i < methodParamTypes.length; i++) { + Class param = methodParamTypes[i]; + if (!param.equals(interfaceParamTypes[i])) { + break; + } + if (i == methodParamTypes.length - 1) { + found = true; + } + } + } + } + if (found) { + break; + } + } + } + if (!found) { + return false; + } + } + return true; + } + +} + +/* + * 1) public setter methods that are not included in any service interface 2) protected setter methods 3) public or + * protected fields unless there is a setter method for the same name If the type associated with the member is an array + * or a java.util.Collection, then the basetype will be the element type of the array or the parameterized type of the + * Collection, otherwise the basetype will be the member type. If the basetype is an interface with an @Remotable or + * @Service annotation then the member will be defined as a reference, otherwise it will be defined as a property. + * + * + */ diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java new file mode 100644 index 0000000000..4581faa872 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegcal use of {@link org.osoa.sca.annotations.Callback} on a reference + * + * @version $Rev$ $Date$ + */ +public class IllegalCallbackReferenceException extends ProcessingException { + + public IllegalCallbackReferenceException(String message) { + super(message); + } + + public IllegalCallbackReferenceException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java new file mode 100644 index 0000000000..8c56cade83 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Context} + * + * @version $Rev$ $Date$ + */ +public class IllegalContextException extends ProcessingException { + + public IllegalContextException(String message) { + super(message); + } + + public IllegalContextException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java new file mode 100644 index 0000000000..fee42ea5c8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Destroy} + * + * @version $Rev$ $Date$ + */ +public class IllegalDestructorException extends ProcessingException { + + public IllegalDestructorException(String message) { + super(message); + } + + public IllegalDestructorException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java new file mode 100644 index 0000000000..219074b785 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal signature for a method decorated with {@link @org.osoa.sca.annotations.Init} + * + * @version $Rev$ $Date$ + */ +public class IllegalInitException extends ProcessingException { + public IllegalInitException(String message) { + super(message); + } + + public IllegalInitException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java new file mode 100644 index 0000000000..11137bcaba --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal reference definition in a component type + * + * @version $Rev$ $Date$ + */ +public class IllegalReferenceException extends ProcessingException { + + public IllegalReferenceException(String message) { + super(message); + } + + public IllegalReferenceException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java new file mode 100644 index 0000000000..e25c1174e2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalResourceException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal resource definition in a component type + * + * @version $Rev$ $Date$ + */ +public class IllegalResourceException extends ProcessingException { + + public IllegalResourceException(String message) { + super(message); + } + + public IllegalResourceException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java new file mode 100644 index 0000000000..1d9079636a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal use of the {@link @org.osoa.sca.annotations.Service} annotation + * + * @version $Rev$ $Date$ + */ +public class IllegalServiceDefinitionException extends ProcessingException { + + public IllegalServiceDefinitionException(String message) { + super(message); + } + + public IllegalServiceDefinitionException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java new file mode 100644 index 0000000000..44e35fab14 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java @@ -0,0 +1,469 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Member; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.core.idl.java.IllegalCallbackException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.implementation.java.DuplicatePropertyException; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.ServiceContract; +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; +import org.apache.tuscany.api.annotation.Resource; + +/** + * The default implementation of an ImplementationProcessorService + * + * @version $Rev$ $Date$ + */ +public class ImplementationProcessorServiceImpl implements ImplementationProcessorService { + private JavaInterfaceProcessorRegistry registry; + private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension(); + + public ImplementationProcessorServiceImpl(@Autowire JavaInterfaceProcessorRegistry registry) { + this.registry = registry; + } + + public JavaMappedService createService(Class interfaze) throws InvalidServiceContractException { + JavaMappedService service = new JavaMappedService(); + service.setName(interfaze.getSimpleName()); + service.setRemotable(interfaze.getAnnotation(Remotable.class) != null); + ServiceContract contract = registry.introspect(interfaze, false); + service.setServiceContract(contract); + return service; + } + + public void processCallback(Class interfaze, ServiceContract contract) throws IllegalCallbackException { + Callback callback = interfaze.getAnnotation(Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + Class callbackClass = callback.value(); + contract.setCallbackClass(callbackClass); + contract.setCallbackName(getBaseName(callbackClass)); + } else if (callback != null && Void.class.equals(callback.value())) { + throw new IllegalCallbackException("No callback interface specified on annotation", interfaze.getName()); + } + } + + public boolean areUnique(Class[] collection) { + if (collection.length == 0) { + return true; + } + return areUnique(collection, 0); + } + + public void addName(List names, int pos, String name) { + if (names.size() < pos) { + for (int i = 0; i < pos; i++) { + names.add(i, ""); + } + names.add(name); + } else if (names.size() > pos) { + names.remove(pos); + names.add(pos, name); + } else { + names.add(pos, name); + } + } + + public boolean processParam( + Class param, + Type genericParam, + Annotation[] paramAnnotations, + String[] constructorNames, + int pos, + PojoComponentType> type, + List injectionNames) throws ProcessingException { + boolean processed = false; + for (Annotation annot : paramAnnotations) { + if (Autowire.class.equals(annot.annotationType())) { + processed = true; + processAutowire(annot, constructorNames, pos, param, genericParam, type, injectionNames); + } else if (Property.class.equals(annot.annotationType())) { + processed = true; + processProperty(annot, constructorNames, pos, type, param, genericParam, injectionNames); + } else if (Reference.class.equals(annot.annotationType())) { + processed = true; + processReference(annot, constructorNames, pos, type, param, genericParam, injectionNames); + } else if (Resource.class.equals(annot.annotationType())) { + processed = true; + processResource((Resource) annot, constructorNames, pos, type, param, injectionNames); + } + } + return processed; + } + + public boolean injectionAnnotationsPresent(Annotation[][] annots) { + for (Annotation[] annotations : annots) { + for (Annotation annotation : annotations) { + Class annotType = annotation.annotationType(); + if (annotType.equals(Autowire.class) || annotType.equals(Property.class) + || annotType.equals(Reference.class) + || annotType.equals(Resource.class)) { + return true; + } + } + } + return false; + } + + public JavaMappedReference createReference(String name, Member member, Class paramType) + throws ProcessingException { + JavaMappedReference reference = new JavaMappedReference(); + reference.setName(name); + reference.setMember(member); + //reference.setRequired(false); + ServiceContract contract; + try { + contract = registry.introspect(paramType, false); + } catch (InvalidServiceContractException e1) { + throw new ProcessingException(e1); + } + try { + processCallback(paramType, contract); + } catch (IllegalCallbackException e) { + throw new ProcessingException(e); + } + reference.setServiceContract(contract); + return reference; + } + + /** + * Determines if all the members of a collection have unique types + * + * @param collection the collection to analyze + * @param start the position in the collection to start + * @return true if the types are unique + */ + private boolean areUnique(Class[] collection, int start) { + Object compare = collection[start]; + for (int i = start + 1; i < collection.length; i++) { + if (compare.equals(collection[i])) { + return false; + } + } + if (start + 1 < collection.length) { + return areUnique(collection, start + 1); + } else { + return true; + } + } + + /** + * Processes autowire metadata for a constructor parameter + * + * @param annot the autowire annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param param the parameter type + * @param type the component type associated with the implementation being processed + * @param injectionNames the collection of injection names to update + * @throws InvalidAutowireException + * @throws InvalidConstructorException + */ + private void processAutowire( + Annotation annot, + String[] constructorNames, + int pos, + Class param, + Type genericParam, + PojoComponentType> type, + List injectionNames) throws ProcessingException { + // the param is marked as an autowire + Autowire autowireAnnot = (Autowire) annot; + JavaMappedReference reference = new JavaMappedReference(); + reference.setAutowire(true); + String name = autowireAnnot.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length > 1 && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) { + throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at " + + (pos + 1)); + } else if (constructorNames.length == 1 && constructorNames[0].length() == 0) { + // special case when @Constructor present with all autowire params not specifying any name + name = param.getName() + String.valueOf(pos); + } else if (constructorNames.length == 1 + && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) { + throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at " + + (pos + 1)); + } else if (constructorNames.length == 1 && constructorNames[0].length() > 0) { + name = constructorNames[pos]; + } else if (constructorNames.length == 0 || constructorNames[pos].length() == 0) { + name = param.getName() + String.valueOf(pos); + } else { + name = constructorNames[pos]; + } + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + String paramNum = String.valueOf(pos + 1); + throw new InvalidConstructorException("Name specified by @Constructor does not match autowire name", + paramNum); + } + reference.setName(name); + boolean required = autowireAnnot.required(); + //reference.setRequired(required); + try { + Class rawType = param; + if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_N); + } else { + reference.setMultiplicity(Multiplicity.ZERO_N); + } + } else { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_ONE); + } else { + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } + } + Class baseType = getBaseType(rawType, genericParam); + ServiceContract contract = registry.introspect(baseType, false); + reference.setServiceContract(contract); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getReferences().put(name, reference); + addName(injectionNames, pos, name); + } + + /** + * Processes parameter metadata for a constructor parameter + * + * @param annot the parameter annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param type the component type associated with the implementation being processed + * @param param the parameter type + * @param explicitNames the collection of injection names to update + * @throws ProcessingException + */ + @SuppressWarnings("unchecked") + private void processProperty( + Annotation annot, + String[] constructorNames, + int pos, + PojoComponentType> type, + Class param, + Type genericParam, + List explicitNames) throws ProcessingException { + // the param is marked as a property + Property propAnnot = (Property) annot; + JavaMappedProperty property = new JavaMappedProperty(); + Class baseType = getBaseType(param, genericParam); + if (param.isArray() || Collection.class.isAssignableFrom(param)) { + property.setMany(true); + } + property.setJavaType(baseType); + String name = propAnnot.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length < pos + 1 || constructorNames[pos] == null + || constructorNames[pos].length() == 0) { + throw new InvalidPropertyException("No name specified for property parameter " + (pos + 1)); + } + name = constructorNames[pos]; + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + String paramNum = String.valueOf(pos + 1); + throw new InvalidConstructorException("Name specified by @Constructor does not match property name", + paramNum); + } + if (type.getProperties().get(name) != null) { + throw new DuplicatePropertyException(name); + } + property.setName(name); + property.setMustSupply(propAnnot.required()); + + String xmlType = propAnnot.xmlType(); + if (xmlType != null && xmlType.length() != 0) { + property.setXmlType(QName.valueOf(xmlType)); + } else { + TypeInfo typeInfo = typeMapper.getXMLType(property.getJavaType()); + if (typeInfo != null) { + property.setXmlType(typeInfo.getQName()); + } + } + type.getProperties().put(name, property); + addName(explicitNames, pos, name); + } + + /** + * Processes reference metadata for a constructor parameter + * + * @param annot the parameter annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param type the component type associated with the implementation being processed + * @param param the parameter type + * @param explicitNames the collection of injection names to update + * @throws ProcessingException + */ + private void processReference( + Annotation annot, + String[] constructorNames, + int pos, + PojoComponentType> type, + Class param, + Type genericParam, + List explicitNames) throws ProcessingException { + + // TODO multiplicity + // the param is marked as a reference + Reference refAnnotation = (Reference) annot; + JavaMappedReference reference = new JavaMappedReference(); + String name = refAnnotation.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length < pos + 1 || constructorNames[pos] == null + || constructorNames[pos].length() == 0) { + throw new InvalidReferenceException("No name specified for reference parameter " + (pos + 1)); + } + name = constructorNames[pos]; + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + String paramNum = String.valueOf(pos + 1); + throw new InvalidConstructorException("Name specified by @Constructor does not match reference name", + paramNum); + } + if (type.getReferences().get(name) != null) { + throw new DuplicateReferenceException(name); + } + reference.setName(name); + boolean required = refAnnotation.required(); + //reference.setRequired(required); + try { + Class rawType = param; + if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_N); + } else { + reference.setMultiplicity(Multiplicity.ZERO_N); + } + } else { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_ONE); + } else { + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } + } + Class baseType = getBaseType(rawType, genericParam); + ServiceContract contract = registry.introspect(baseType, false); + reference.setServiceContract(contract); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getReferences().put(name, reference); + addName(explicitNames, pos, name); + } + + /** + * Processes resource metadata for a constructor parameter + * + * @param resourceAnnot the resource annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param type the component type associated with the implementation being processed + * @param param the parameter type + * @param explicitNames the collection of injection names to update + * @throws ProcessingException + */ + private void processResource( + Resource resourceAnnot, + String[] constructorNames, + int pos, + PojoComponentType> type, + Class param, + List explicitNames) throws ProcessingException { + + org.apache.tuscany.spi.implementation.java.Resource resource = + new org.apache.tuscany.spi.implementation.java.Resource(); + String name = resourceAnnot.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length < pos + 1 || constructorNames[pos] == null + || constructorNames[pos].length() == 0) { + String paramNum = String.valueOf(pos + 1); + throw new InvalidResourceException("No name specified for resource parameter", paramNum); + } + name = constructorNames[pos]; + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + String paramNum = String.valueOf(pos + 1); + throw new InvalidConstructorException("Name specified by @Constructor does not match resource name", + paramNum); + } + if (type.getResources().get(name) != null) { + throw new DuplicateResourceException(name); + } + resource.setName(name); + resource.setOptional(resourceAnnot.optional()); + resource.setType(param); + String mappedName = resourceAnnot.mappedName(); + if (mappedName.length() > 0) { + resource.setMappedName(mappedName); + } + type.add(resource); + addName(explicitNames, pos, name); + } + + protected static Class getBaseType(Class cls, Type genericType) { + if (cls.isArray()) { + return cls.getComponentType(); + } else if (Collection.class.isAssignableFrom(cls)) { + if (genericType == cls) { + return Object.class; + } else { + ParameterizedType parameterizedType = (ParameterizedType) genericType; + Type baseType = parameterizedType.getActualTypeArguments()[0]; + if (baseType instanceof Class) { + return (Class) baseType; + } else if (baseType instanceof ParameterizedType) { + return (Class) ((ParameterizedType) baseType).getRawType(); + } else { + return null; + } + } + } else { + return cls; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java new file mode 100644 index 0000000000..be5ac78008 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Processes the {@link @Init} annotation on a component implementation and updates the component type with the + * decorated initializer method + * + * @version $Rev$ $Date$ + */ +public class InitProcessor extends ImplementationProcessorExtension { + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + Init annotation = method.getAnnotation(Init.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 0) { + throw new IllegalInitException("Initializer must not have argments", method.toString()); + } + if (type.getInitMethod() != null) { + throw new DuplicateInitException("More than one initializer found on implementaton"); + } + if (Modifier.isProtected(method.getModifiers())) { + method.setAccessible(true); + } + type.setInitMethod(method); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java new file mode 100644 index 0000000000..92a2a0923d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link org.apache.tuscany.spi.annotation.Autowire} + * + * @version $Rev$ $Date$ + */ +public class InvalidAutowireException extends ProcessingException { + + public InvalidAutowireException(String message) { + super(message); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java new file mode 100644 index 0000000000..a2dd3f09c4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid constructor definition, e.g. when the number of injection names specified in {@link + * org.osoa.sca.annotations.Constructor} do not match the number of actual constructor parameters + * + * @version $Rev$ $Date$ + */ +public class InvalidConstructorException extends ProcessingException { + + public InvalidConstructorException(String message) { + super(message); + } + + public InvalidConstructorException(String message, String identifier) { + super(message, identifier); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java new file mode 100644 index 0000000000..28bd65200e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConversationalImplementation.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Raised when an implementation specifies improper conversational metadata + * + * @version $Rev$ $Date$ + */ +public class InvalidConversationalImplementation extends ProcessingException { + + public InvalidConversationalImplementation(String message) { + super(message); + } + + public InvalidConversationalImplementation(String message, String identifier) { + super(message, identifier); + } + + public InvalidConversationalImplementation(String message, Throwable cause) { + super(message, cause); + } + + public InvalidConversationalImplementation(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java new file mode 100644 index 0000000000..5d4c245764 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link org.osoa.sca.annotations.Property} + * + * @version $Rev$ $Date$ + */ +public class InvalidPropertyException extends ProcessingException { + + public InvalidPropertyException(String message) { + super(message); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java new file mode 100644 index 0000000000..8fbc07aa1c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link org.osoa.sca.annotations.Reference} + * + * @version $Rev$ $Date$ + */ +public class InvalidReferenceException extends ProcessingException { + + public InvalidReferenceException(String message) { + super(message); + } + + public InvalidReferenceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidReferenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java new file mode 100644 index 0000000000..4ed6d93994 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidResourceException.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link @org.apache.tuscany.api.annotation.Resource} + * + * @version $Rev$ $Date$ + */ +public class InvalidResourceException extends ProcessingException { + + public InvalidResourceException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java new file mode 100644 index 0000000000..f3d0367661 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when a service type specified by an {@link org.osoa.sca.annotations.Service} annotation is invalid, e.g. it is + * not an interface + * + * @version $Rev$ $Date$ + */ +public class InvalidServiceType extends ProcessingException { + + public InvalidServiceType(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java new file mode 100644 index 0000000000..e7acce2973 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; + +import org.apache.tuscany.api.annotation.Monitor; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.apache.tuscany.host.MonitorFactory; + +/** + * Processes an {@link @Monitor} annotation, updating the component type with corresponding {@link + * org.apache.tuscany.spi.implementation.java.JavaMappedProperty} + * + * @version $Rev$ $Date$ + */ +public class MonitorProcessor extends AbstractPropertyProcessor { + private MonitorFactory monitorFactory; + + public MonitorProcessor(@Autowire MonitorFactory monitorFactory, @Autowire ImplementationProcessorService service) { + super(Monitor.class, service); + this.monitorFactory = monitorFactory; + } + + protected String getName(Monitor annotation) { + return null; + } + + protected void initProperty(JavaMappedProperty property, + Monitor annotation, + CompositeComponent parent, + DeploymentContext context) { + Class javaType = property.getJavaType(); + property.setDefaultValueFactory(new SingletonObjectFactory(monitorFactory.getMonitor(javaType))); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java new file mode 100644 index 0000000000..f36b7900a4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when a suitable constructor for a component implementation cannot be found + * + * @version $Rev$ $Date$ + */ +public class NoConstructorException extends ProcessingException { + + public NoConstructorException() { + } + + public NoConstructorException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java new file mode 100644 index 0000000000..000422ee6f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.osoa.sca.annotations.Property; + +/** + * Processes an {@link @Property} annotation, updating the component type with + * corresponding {@link JavaMappedProperty} + * + * @version $Rev$ $Date$ + */ +public class PropertyProcessor extends AbstractPropertyProcessor { + private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension(); + + public PropertyProcessor(@Autowire + ImplementationProcessorService service) { + super(Property.class, service); + } + + protected String getName(Property annotation) { + return annotation.name(); + } + + protected void initProperty(JavaMappedProperty property, + Property annotation, + CompositeComponent parent, + DeploymentContext context) { + String xmlType = annotation.xmlType(); + if (xmlType != null && xmlType.length() != 0) { + property.setXmlType(QName.valueOf(annotation.xmlType())); + } else { + TypeInfo type = typeMapper.getXMLType(property.getJavaType()); + if (type != null) { + property.setXmlType(type.getQName()); + } + } + } + + public void visitConstructor(CompositeComponent parent, + Constructor constructor, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + // override since heuristic pojo processor evalautes properties + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java new file mode 100644 index 0000000000..12aba4c94e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collection; + +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.ServiceContract; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +/** + * Processes an {@link @Reference} annotation, updating the component type with corresponding {@link + * org.apache.tuscany.spi.implementation.java.JavaMappedReference} + * + * @version $Rev$ $Date$ + */ +public class ReferenceProcessor extends ImplementationProcessorExtension { + + private JavaInterfaceProcessorRegistry regsitry; + + public ReferenceProcessor(@Autowire + JavaInterfaceProcessorRegistry registry) { + this.regsitry = registry; + } + + public void visitMethod(CompositeComponent parent, + Method method, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + Reference annotation = method.getAnnotation(Reference.class); + Autowire autowire = method.getAnnotation(Autowire.class); + boolean isAutowire = autowire != null; + if (annotation == null && !isAutowire) { + return; // Not a reference or autowire annotation. + } + if (method.getParameterTypes().length != 1) { + throw new IllegalReferenceException("Setter must have one parameter", method.toString()); + } + // process autowire required first let reference override. or if + // conflicting should this fault? + boolean required = false; + if (isAutowire) { + required = autowire.required(); + } + + String name = null; + + if (annotation != null) { + if (annotation.name() != null && annotation.name().length() > 0) { + name = annotation.name(); + } + required = annotation.required(); + } + if (name == null) { + name = toPropertyName(method.getName()); + } + if (type.getReferences().get(name) != null) { + throw new DuplicateReferenceException(name); + } + + JavaMappedReference reference = new JavaMappedReference(); + reference.setMember(method); + reference.setAutowire(isAutowire); + //reference.setRequired(required); + reference.setName(name); + ServiceContract contract; + try { + Class rawType = method.getParameterTypes()[0]; + if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_N); + } else { + reference.setMultiplicity(Multiplicity.ZERO_N); + } + } else { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_ONE); + } else { + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } + } + Class baseType = getBaseType(rawType, method.getGenericParameterTypes()[0]); + contract = regsitry.introspect(baseType); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + reference.setServiceContract(contract); + type.getReferences().put(name, reference); + } + + public void visitField(CompositeComponent parent, + Field field, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + Reference annotation = field.getAnnotation(Reference.class); + boolean autowire = field.getAnnotation(Autowire.class) != null; + if (annotation == null && !autowire) { + return; + } + String name = field.getName(); + boolean required = false; + if (annotation != null) { + if (annotation.name() != null) { + name = annotation.name(); + } + required = annotation.required(); + } + if (name.length() == 0) { + name = field.getName(); + } + if (type.getReferences().get(name) != null) { + throw new DuplicateReferenceException(name); + } + JavaMappedReference reference = new JavaMappedReference(); + reference.setMember(field); + //reference.setRequired(required); + reference.setAutowire(autowire); + reference.setName(name); + ServiceContract contract; + try { + Class rawType = field.getType(); + if (rawType.isArray() || Collection.class.isAssignableFrom(rawType)) { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_N); + } else { + reference.setMultiplicity(Multiplicity.ZERO_N); + } + } else { + if (required) { + reference.setMultiplicity(Multiplicity.ONE_ONE); + } else { + reference.setMultiplicity(Multiplicity.ZERO_ONE); + } + } + Class baseType = getBaseType(rawType, field.getGenericType()); + contract = regsitry.introspect(baseType); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + reference.setServiceContract(contract); + type.getReferences().put(name, reference); + } + + public void visitConstructor(CompositeComponent parent, + Constructor constructor, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.java new file mode 100644 index 0000000000..29773f5e80 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ResourceProcessor.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.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.implementation.java.Resource; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +/** + * Processes an {@link @Resource} annotation, updating the component type with corresponding {@link + * org.apache.tuscany.spi.implementation.java.Resource} + * + * @version $Rev$ $Date$ + */ +public class ResourceProcessor extends ImplementationProcessorExtension { + + public ResourceProcessor() { + } + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + org.apache.tuscany.api.annotation.Resource annotation = + method.getAnnotation(org.apache.tuscany.api.annotation.Resource.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalResourceException("Resource setter must have one parameter", method.toString()); + } + String name = annotation.name(); + if (name.length() < 1) { + name = toPropertyName(method.getName()); + } + if (type.getResources().get(name) != null) { + throw new DuplicateResourceException(name); + } + + String mappedName = annotation.mappedName(); + Resource resource = new Resource(); + resource.setMember(method); + resource.setType(method.getParameterTypes()[0]); + resource.setOptional(annotation.optional()); + resource.setName(name); + if (mappedName.length() > 0) { + resource.setMappedName(mappedName); + } + type.add(resource); + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + + org.apache.tuscany.api.annotation.Resource annotation = + field.getAnnotation(org.apache.tuscany.api.annotation.Resource.class); + if (annotation == null) { + return; + } + String name = annotation.name(); + if (name.length() < 1) { + name = field.getName(); + } + if (type.getResources().get(name) != null) { + throw new DuplicateResourceException(name); + } + + String mappedName = annotation.mappedName(); + Resource resource = new Resource(); + resource.setMember(field); + resource.setType(field.getType()); + resource.setOptional(annotation.optional()); + resource.setName(name); + if (mappedName.length() > 0) { + resource.setMappedName(mappedName); + } + type.add(resource); + } + + public void visitConstructor(CompositeComponent parent, Constructor constructor, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java new file mode 100644 index 0000000000..634aff0377 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Scope; + +/** + * Processes the {@link Scope} annotation and updates the component type with the corresponding implmentation scope + * + * @version $Rev$ $Date$ + */ +public class ScopeProcessor extends ImplementationProcessorExtension { + + public void visitClass(CompositeComponent parent, Class clazz, + PojoComponentType> type, + DeploymentContext context) + throws ProcessingException { + org.osoa.sca.annotations.Scope annotation = clazz.getAnnotation(org.osoa.sca.annotations.Scope.class); + if (annotation == null) { + type.setImplementationScope(Scope.STATELESS); + return; + } + String name = annotation.value(); + Scope scope; + if ("COMPOSITE".equals(name)) { + scope = Scope.COMPOSITE; + } else if ("SESSION".equals(name)) { + scope = Scope.SESSION; + } else if ("CONVERSATION".equals(name)) { + scope = Scope.CONVERSATION; + } else if ("REQUEST".equals(name)) { + scope = Scope.REQUEST; + } else if ("SYSTEM".equals(name)) { + scope = Scope.SYSTEM; + } else { + scope = new Scope(name); + } + type.setImplementationScope(scope); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java new file mode 100644 index 0000000000..6f96c92006 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Set; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.model.ServiceContract; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllInterfaces; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +/** + * Processes an {@link org.osoa.sca.annotations.Service} annotation and updates the component type with corresponding + * {@link JavaMappedService}s. Also processes related {@link org.osoa.sca.annotations.Callback} annotations. + * + * @version $Rev$ $Date$ + */ +public class ServiceProcessor extends ImplementationProcessorExtension { + + private ImplementationProcessorService implService; + + public ServiceProcessor(@Autowire ImplementationProcessorService implService) { + this.implService = implService; + } + + public void visitClass(CompositeComponent parent, Class clazz, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + org.osoa.sca.annotations.Service annotation = clazz.getAnnotation(org.osoa.sca.annotations.Service.class); + if (annotation == null) { + // scan intefaces for remotable + Set interfaces = getAllInterfaces(clazz); + for (Class interfaze : interfaces) { + if (interfaze.getAnnotation(Remotable.class) != null) { + JavaMappedService service; + try { + service = implService.createService(interfaze); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + return; + } + Class[] interfaces = annotation.interfaces(); + if (interfaces.length == 0) { + Class interfaze = annotation.value(); + if (Void.class.equals(interfaze)) { + throw new IllegalServiceDefinitionException("No interfaces specified"); + } else { + interfaces = new Class[1]; + interfaces[0] = interfaze; + } + } + for (Class interfaze : interfaces) { + if (!interfaze.isInterface()) { + throw new InvalidServiceType("Service must be an interface", interfaze.getName()); + } + JavaMappedService service; + try { + service = implService.createService(interfaze); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + + + public void visitMethod(CompositeComponent parent, + Method method, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + + Callback annotation = method.getAnnotation(Callback.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 1) { + throw new IllegalCallbackReferenceException("Setter must have one parameter", method.toString()); + } + String name = toPropertyName(method.getName()); + JavaMappedService callbackService = null; + Class callbackClass = method.getParameterTypes()[0]; + for (JavaMappedService service : type.getServices().values()) { + ServiceContract serviceContract = service.getServiceContract(); + if (serviceContract.getCallbackClass().equals(callbackClass)) { + callbackService = service; + } + } + if (callbackService == null) { + throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface"); + } + callbackService.setCallbackReferenceName(name); + callbackService.setCallbackMember(method); + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType> type, + DeploymentContext context) throws ProcessingException { + + Callback annotation = field.getAnnotation(Callback.class); + if (annotation == null) { + return; + } + String name = field.getName(); + JavaMappedService callbacksService = null; + Class callbackClass = field.getType(); + for (JavaMappedService service : type.getServices().values()) { + ServiceContract serviceContract = service.getServiceContract(); + if (serviceContract.getCallbackClass().equals(callbackClass)) { + callbacksService = service; + } + } + if (callbacksService == null) { + throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface"); + } + callbacksService.setCallbackReferenceName(name); + callbacksService.setCallbackMember(field); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java new file mode 100644 index 0000000000..8a0d4afc3d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when a service interface cannot be determined based on a heuristic evaluation of an implementation + * + * @version $Rev$ $Date$ + */ +public class ServiceTypeNotFoundException extends ProcessingException { + + public ServiceTypeNotFoundException(String message) { + super(message); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java new file mode 100644 index 0000000000..a7868349a6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +/** + * Thrown when a method or field marked with {@link org.osoa.sca.annotations.Context} takes an unknown type + * + * @version $Rev$ $Date$ + */ +public class UnknownContextTypeException extends IllegalContextException { + + public UnknownContextTypeException(String message) { + super(message); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java new file mode 100644 index 0000000000..33cbbe1232 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.builder; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Map; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.host.ResourceHost; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.Resource; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.injection.ResourceObjectFactory; + +/** + * Produces system atomic components from a component definition + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemComponentBuilder extends ComponentBuilderExtension { + private ResourceHost host; + + protected Class getImplementationType() { + return SystemImplementation.class; + } + + @Autowire + public void setHost(ResourceHost host) { + this.host = host; + } + + @SuppressWarnings("unchecked") + public AtomicComponent build(CompositeComponent parent, + ComponentDefinition definition, + DeploymentContext deploymentContext) throws BuilderConfigException { + PojoComponentType> componentType = + definition.getImplementation().getComponentType(); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setParent(parent); + if (definition.getInitLevel() != null) { + configuration.setInitLevel(definition.getInitLevel()); + } else { + configuration.setInitLevel(componentType.getInitLevel()); + } + Method initMethod = componentType.getInitMethod(); + if (initMethod != null) { + configuration.setInitInvoker(new MethodEventInvoker(initMethod)); + } + Method destroyMethod = componentType.getDestroyMethod(); + if (destroyMethod != null) { + configuration.setDestroyInvoker(new MethodEventInvoker(destroyMethod)); + } + // setup property injection sites + for (JavaMappedProperty property : componentType.getProperties().values()) { + configuration.addPropertySite(property.getName(), property.getMember()); + } + // setup reference injection sites + for (JavaMappedReference reference : componentType.getReferences().values()) { + Member member = reference.getMember(); + if (member != null) { + // could be null if the reference is mapped to a constructor + configuration.addReferenceSite(reference.getName(), member); + } + } + + for (Resource resource : componentType.getResources().values()) { + Member member = resource.getMember(); + if (member != null) { + // could be null if the resource is mapped to a constructor + configuration.addResourceSite(resource.getName(), member); + } + } + + // setup constructor injection + ConstructorDefinition ctorDef = componentType.getConstructorDefinition(); + Constructor constr = ctorDef.getConstructor(); + PojoObjectFactory instanceFactory = new PojoObjectFactory(constr); + configuration.setInstanceFactory(instanceFactory); + configuration.getConstructorParamNames().addAll(ctorDef.getInjectionNames()); + for (Class clazz : constr.getParameterTypes()) { + configuration.addConstructorParamType(clazz); + } + configuration.setName(definition.getName()); + SystemAtomicComponentImpl component = new SystemAtomicComponentImpl(configuration); + // handle properties + Map> propertyValues = definition.getPropertyValues(); + processProperties(propertyValues, componentType.getProperties().values(), component); + + // handle resources + for (Resource resource : componentType.getResources().values()) { + String name = resource.getName(); + boolean optional = resource.isOptional(); + Class type = (Class) resource.getType(); + ResourceObjectFactory factory; + String mappedName = resource.getMappedName(); + if (mappedName == null) { + // by type + factory = new ResourceObjectFactory(type, optional, parent, host); + } else { + factory = new ResourceObjectFactory(type, mappedName, optional, parent, host); + } + component.addResourceFactory(name, factory); + + } + return component; + } + +// private void processReferences(ComponentDefinition definition, +// Map references, +// CompositeComponent parent, +// SystemAtomicComponentImpl component) { +// // no proxies needed for system components +// for (ReferenceTarget target : definition.getReferenceTargets().values()) { +// String referenceName = target.getReferenceName(); +// JavaMappedReference referenceDefiniton = references.get(referenceName); +// Class interfaze = referenceDefiniton.getServiceContract().getInterfaceClass(); +// OutboundWire wire; +// if (referenceDefiniton.isAutowire()) { +// boolean required = referenceDefiniton.isRequired(); +// wire = new SystemOutboundAutowire(referenceName, interfaze, parent, required); +// } else { +// //FIXME support multiplicity! +// assert target.getTargets().size() == 1 : "Multiplicity not yet implemented"; +// QualifiedName targetName = new QualifiedName(target.getTargets().get(0).getPath()); +// wire = new SystemOutboundWireImpl(referenceName, targetName, interfaze); +// } +// component.addOutboundWire(wire); +// } +// } + + private void processProperties(Map> propertyValues, + Collection> properties, + SystemAtomicComponentImpl component) { + for (JavaMappedProperty property : properties) { + PropertyValue value = propertyValues.get(property.getName()); + ObjectFactory factory; + if (value != null) { + factory = value.getValueFactory(); + } else { + factory = property.getDefaultValueFactory(); + } + if (factory != null) { + component.addPropertyFactory(property.getName(), factory); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java new file mode 100644 index 0000000000..c43b0d1ee9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.apache.tuscany.core.implementation.PojoAtomicComponent; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.wire.OptimizedWireObjectFactory; + +/** + * Default implementation of a system atomic context + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemAtomicComponentImpl extends PojoAtomicComponent { + + public SystemAtomicComponentImpl(PojoConfiguration configuration) { + super(configuration); + scope = Scope.COMPOSITE; + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation, InboundWire callbackWire) { + return null; + } + + public boolean isSystem() { + return true; + } + + protected ObjectFactory createWireFactory(Class interfaze, OutboundWire wire) { + return new OptimizedWireObjectFactory(wire); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java new file mode 100644 index 0000000000..2c7141044b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import java.net.URL; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * Loads a system component type + * + * @version $Rev$ $Date$ + */ +public class SystemComponentTypeLoader extends ComponentTypeLoaderExtension { + private Introspector introspector; + + public SystemComponentTypeLoader() { + } + + public SystemComponentTypeLoader(Introspector introspector) { + this.introspector = introspector; + } + + public SystemComponentTypeLoader(LoaderRegistry loaderRegistry, Introspector introspector) { + super(loaderRegistry); + this.introspector = introspector; + } + + //FIXME autowire to support multiple interfaces + @Autowire + public void setIntrospector(IntrospectionRegistry introspector) { + this.introspector = introspector; + } + + public void load(CompositeComponent parent, + SystemImplementation implementation, + DeploymentContext deploymentContext) throws LoaderException { + Class implClass = implementation.getImplementationClass(); + URL sidefile = implClass.getResource(JavaIntrospectionHelper.getBaseName(implClass) + ".componentType"); + PojoComponentType componentType; + if (sidefile == null) { + componentType = loadByIntrospection(parent, implementation, deploymentContext); + } else { + componentType = loadFromSidefile(sidefile, deploymentContext); + } + // this means system components are always composite scoped + componentType.setImplementationScope(Scope.COMPOSITE); + implementation.setComponentType(componentType); + } + + protected Class getImplementationClass() { + return SystemImplementation.class; + } + + protected PojoComponentType loadByIntrospection(CompositeComponent parent, + SystemImplementation implementation, + DeploymentContext deploymentContext) throws ProcessingException { + PojoComponentType> componentType = + new PojoComponentType>(); + Class implClass = implementation.getImplementationClass(); + introspector.introspect(parent, implClass, componentType, deploymentContext); + return componentType; + } + + + protected PojoComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException { + return loaderRegistry.load(null, null, url, PojoComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java new file mode 100644 index 0000000000..0e05041ea5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import java.net.URL; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.CompositeComponentType; + +import org.apache.tuscany.core.deployer.ChildDeploymentContext; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; + +/** + * Loads a system composite component type + * + * @version $Rev$ $Date$ + */ +public class SystemCompositeComponentTypeLoader extends ComponentTypeLoaderExtension { + public SystemCompositeComponentTypeLoader() { + } + + public SystemCompositeComponentTypeLoader(LoaderRegistry loaderRegistry) { + super(loaderRegistry); + } + + protected Class getImplementationClass() { + return SystemCompositeImplementation.class; + } + + public void load(CompositeComponent parent, SystemCompositeImplementation implementation, + DeploymentContext deploymentContext) + throws LoaderException { + URL scdlLocation = implementation.getScdlLocation(); + if (scdlLocation == null) { + throw new LoaderException("SCDL location not found"); + } + ClassLoader cl = implementation.getClassLoader(); + deploymentContext = new ChildDeploymentContext(deploymentContext, cl, scdlLocation); + CompositeComponentType componentType = loadFromSidefile(parent, scdlLocation, deploymentContext); + implementation.setComponentType(componentType); + } + + + protected CompositeComponentType loadFromSidefile(CompositeComponent parent, + URL url, + DeploymentContext deploymentContext) + throws LoaderException { + return loaderRegistry.load(parent, null, url, CompositeComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java new file mode 100644 index 0000000000..d5d4269880 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.ModelObject; + +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; + +/** + * Loads information for a system implementation + * + * @version $Rev$ $Date$ + */ +public class SystemImplementationLoader extends LoaderExtension { + public static final QName SYSTEM_IMPLEMENTATION = + new QName("http://tuscany.apache.org/xmlns/system/1.0-SNAPSHOT", "implementation.system"); + + public SystemImplementationLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public SystemImplementation load(CompositeComponent parent, + ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + assert SYSTEM_IMPLEMENTATION.equals(reader.getName()); + SystemImplementation implementation = new SystemImplementation(); + String implClass = reader.getAttributeValue(null, "class"); + Class implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader()); + implementation.setImplementationClass(implementationClass); + registry.loadComponentType(parent, implementation, deploymentContext); + while (true) { + int code = reader.next(); + if (code == XMLStreamConstants.START_ELEMENT) { + throw new UnrecognizedElementException(reader.getName()); + } else if (code == XMLStreamConstants.END_ELEMENT) { + return implementation; + } + } + } + + public QName getXMLType() { + return SYSTEM_IMPLEMENTATION; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java new file mode 100644 index 0000000000..e634609c5b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.model; + +import java.net.URL; + +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; + +/** + * Represents a system composite type + * + * @version $Rev$ $Date$ + */ +public class SystemCompositeImplementation extends Implementation { + private URL scdlLocation; + private ClassLoader classLoader; + + public SystemCompositeImplementation() { + } + + public SystemCompositeImplementation(CompositeComponentType componentType) { + super(componentType); + } + + public URL getScdlLocation() { + return scdlLocation; + } + + public void setScdlLocation(URL scdlLocation) { + this.scdlLocation = scdlLocation; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java new file mode 100644 index 0000000000..ce48ed3fe5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.model; + +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.AtomicImplementation; + +/** + * Represents the system composite implementation + * + * @version $Rev$ $Date$ + */ +public class SystemImplementation extends AtomicImplementation { + private Class implementationClass; + + public SystemImplementation(PojoComponentType componentType, Class implementationClass) { + super(componentType); + this.implementationClass = implementationClass; + } + + public SystemImplementation() { + } + + public SystemImplementation(Class implementationClass) { + this.implementationClass = implementationClass; + } + + public Class getImplementationClass() { + return implementationClass; + } + + public void setImplementationClass(Class implementationClass) { + this.implementationClass = implementationClass; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java new file mode 100644 index 0000000000..1a441dcf87 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Array; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an Array + * containing object instances + * + * @version $Rev$ $Date$ + */ +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/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java new file mode 100644 index 0000000000..fc389a23cf --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.WireService; + +/** + * Returns proxy instance for a wire callback + * + * @version $Rev$ $Date$ + */ +public class CallbackWireObjectFactory implements ObjectFactory { + + private WireService wireService; + private Class interfaze; + private InboundWire wire; + + public CallbackWireObjectFactory(Class interfaze, WireService wireService, InboundWire wire) { + this.interfaze = interfaze; + this.wireService = wireService; + this.wire = wire; + } + + public Object getInstance() throws ObjectCreationException { + return wireService.createCallbackProxy(interfaze, wire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java new file mode 100644 index 0000000000..e44c8124d5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CompositeContextObjectFactory.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.core.launcher.CompositeContextImpl; +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.wire.WireService; +import org.osoa.sca.CompositeContext; + +/** + * Creates instances of {@link org.apache.tuscany.core.implementation.composite.ManagedCompositeContext} for injection + * on component implementation instances + * + * @version $Rev$ $Date$ + */ +public class CompositeContextObjectFactory implements ObjectFactory { + private CompositeComponent composite; + private WireService wireService; + + public CompositeContextObjectFactory(CompositeComponent composite, WireService wireService) { + assert composite != null; + assert wireService != null; + this.composite = composite; + this.wireService = wireService; + } + + public CompositeContext getInstance() throws ObjectCreationException { + return new CompositeContextImpl(composite, wireService); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java new file mode 100644 index 0000000000..a422500f3c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; + +/** + * Implementations inject a pre-configured context type (interface) on an instance. + * + * @version $Rev$ $Date$ + */ +public interface ContextInjector extends Injector { + + void setContext(S context) throws ObjectCreationException; + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java new file mode 100644 index 0000000000..8dbc0a3a83 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ConversationIDObjectFactory.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Scope; + +public class ConversationIDObjectFactory implements ObjectFactory { + + private WorkContext workContext; + + public ConversationIDObjectFactory(WorkContext workContext) { + this.workContext = workContext; + } + + public String getInstance() { + return (String)workContext.getIdentifier(Scope.CONVERSATION); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java new file mode 100644 index 0000000000..af2382b36a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +/** + * Performs an invocation on an instance + * + * @version $Rev$ $Date$ + */ +public interface EventInvoker { + + /** + * Performs the invocation on a given instance + * + * @throws ObjectCallbackException + */ + void invokeEvent(T instance) throws ObjectCallbackException; +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java new file mode 100644 index 0000000000..e9f8f42aa1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Field; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.spi.ObjectFactory} on a given field + * + * @version $Rev$ $Date$ + */ +public class FieldInjector 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 isntance + */ + public void inject(T instance) throws ObjectCreationException { + try { + field.set(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Field is not accessible [" + field + "]"); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java new file mode 100644 index 0000000000..c5f037d931 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * Root unchecked exception for the injection package + * + * @version $Rev$ $Date$ + */ +public abstract class InjectionRuntimeException extends TuscanyRuntimeException { + + public InjectionRuntimeException() { + super(); + } + + public InjectionRuntimeException(String message) { + super(message); + } + + + protected InjectionRuntimeException(String message, String identifier) { + super(message, identifier); + } + + public InjectionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + protected InjectionRuntimeException(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } + + public InjectionRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java new file mode 100644 index 0000000000..c2125d8212 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; + +/** + * Implementations inject a pre-configured value on an instance + * + * @version $Rev$ $Date$ + */ +public interface Injector { + + /** + * Inject a value on the given instance + */ + void inject(T instance) throws ObjectCreationException; + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java new file mode 100644 index 0000000000..2e7ff0e754 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class InvalidAccessorException extends InjectionRuntimeException { + + public InvalidAccessorException(String message) { + super(message); + } + + public InvalidAccessorException(String message, String identifier) { + super(message, identifier); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java new file mode 100644 index 0000000000..1a3eaf4d1a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidResourceTypeException.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; + +/** + * Denotes an invalid resource type, i.e. that is not a component + * + * @version $Rev$ $Date$ + */ +public class InvalidResourceTypeException extends ObjectCreationException { + + public InvalidResourceTypeException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIListObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIListObjectFactory.java new file mode 100644 index 0000000000..bf2a7a103e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIListObjectFactory.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * An implementation of ObjectFactory that creates instances by looking them up in a JNDI context. + * + * @version $Rev: 430937 $ $Date: 2006-08-12 06:47:56 +0530 (Sat, 12 Aug 2006) $ + */ +public class JNDIListObjectFactory implements ObjectFactory> { + private final Context context; + private List nameList; + + public JNDIListObjectFactory(Context context, List name) { + this.context = context; + this.nameList = Collections.unmodifiableList(name); + } + + + @SuppressWarnings("unchecked") + public List getInstance() throws ObjectCreationException { + try { + List instanceList = new ArrayList(); + for (int count = 0 ; count < instanceList.size() ; ++count) { + instanceList.add((T) context.lookup(nameList.get(count))); + } + return instanceList; + } catch (NamingException e) { + throw new ObjectCreationException(e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java new file mode 100644 index 0000000000..0189d8245b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * An implementation of ObjectFactory that creates instances by looking them up in a JNDI context. + * + * @version $Rev$ $Date$ + */ +public class JNDIObjectFactory implements ObjectFactory { + private final Context context; + private final String name; + + public JNDIObjectFactory(Context context, String name) { + this.context = context; + this.name = name; + } + + + @SuppressWarnings("unchecked") + public T getInstance() throws ObjectCreationException { + try { + return (T) context.lookup(name); + } catch (NamingException e) { + throw new ObjectCreationException(e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java new file mode 100644 index 0000000000..b261bcda53 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an List + * containing object instances + * + * @version $Rev$ $Date$ + */ +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/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java new file mode 100644 index 0000000000..e43a1e1fa6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Performs an wire on a method of a given instance + * + * @version $Rev$ $Date$ + */ +public class MethodEventInvoker implements EventInvoker { + private final Method method; + + /** + * Intantiates an invoker for the given method + */ + public MethodEventInvoker(Method method) { + assert method != null; + this.method = method; + } + + public void invokeEvent(T instance) throws ObjectCallbackException { + try { + method.invoke(instance, (Object[]) null); + } catch (IllegalArgumentException e) { + String name = method.getName(); + throw new ObjectCallbackException("Exception thrown by callback method [" + name + "]", e.getCause()); + } catch (IllegalAccessException e) { + String name = method.getName(); + throw new AssertionError("Method is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = method.getName(); + throw new ObjectCallbackException("Exception thrown by callback method [" + name + "]", e.getCause()); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java new file mode 100644 index 0000000000..258f0817dd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.spi.ObjectFactory} using a given method + * + * @version $Rev$ $Date$ + */ +public class MethodInjector implements Injector { + private final Method method; + private final ObjectFactory objectFactory; + + public MethodInjector(Method method, ObjectFactory objectFactory) { + assert method != null; + assert objectFactory != null; + this.method = method; + this.method.setAccessible(true); + this.objectFactory = objectFactory; + } + + public void inject(T instance) throws ObjectCreationException { + try { + method.invoke(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (IllegalArgumentException e) { + throw new ObjectCreationException("Exception thrown by setter", method.getName(), e); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by setter", method.getName(), e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java new file mode 100644 index 0000000000..b3109074e3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class NoAccessorException extends InjectionRuntimeException { + public NoAccessorException() { + } + + public NoAccessorException(String message) { + super(message); + } + + public NoAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public NoAccessorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java new file mode 100644 index 0000000000..a86451525b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoMultiplicityTypeException.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +/** + * @version $Rev$ $Date$ + */ +public class NoMultiplicityTypeException extends InjectionRuntimeException { + + public NoMultiplicityTypeException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java new file mode 100644 index 0000000000..ff830aab4b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +/** + * Denotes an error when invoking on an object + * + * @version $Rev$ $Date$ + */ +public class ObjectCallbackException extends InjectionRuntimeException { + + public ObjectCallbackException() { + super(); + } + + public ObjectCallbackException(String message) { + super(message); + } + + public ObjectCallbackException(String message, String identifier) { + super(message, identifier); + } + + public ObjectCallbackException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCallbackException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java new file mode 100644 index 0000000000..cf446a35fc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.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.core.injection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Creates new instances of a Java class + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.core.injection.Injector + */ +public class PojoObjectFactory 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 PojoObjectFactory(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 PojoObjectFactory(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) { + // [rfeng] Set it to null for property with default values + initargs[i] = null; + // String name = ctr.getName(); + // throw new ObjectCallbackException("Null object factory for + // constructor parameter [" + i + "]", name); + } else { + initargs[i] = objectFactory.getInstance(); + } + } + try { + ctr.setAccessible(true); + return ctr.newInstance(initargs); + } catch (IllegalArgumentException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor", name, e); + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor", name, e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java new file mode 100644 index 0000000000..9a9d97a273 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/RequestContextObjectFactory.java @@ -0,0 +1,26 @@ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.WorkContext; + +import org.apache.tuscany.core.implementation.composite.ManagedRequestContext; + +/** + * Creates instances of {@link org.apache.tuscany.core.implementation.composite.ManagedRequestContext} for injection on + * component implementation instances + * + * @version $Rev$ $Date$ + */ +public class RequestContextObjectFactory implements ObjectFactory { + private WorkContext workContext; + + public RequestContextObjectFactory(WorkContext workContext) { + assert workContext != null; + this.workContext = workContext; + } + + public ManagedRequestContext getInstance() throws ObjectCreationException { + return new ManagedRequestContext(workContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java new file mode 100644 index 0000000000..ed3ac20631 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceNotFoundException.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; + +/** + * Denotes an exception thrown when a runtime resource is not found + * + * @version $Rev$ $Date$ + */ +public class ResourceNotFoundException extends ObjectCreationException { + + public ResourceNotFoundException(String message, String identifier) { + super(message, identifier); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java new file mode 100644 index 0000000000..45df502256 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ResourceObjectFactory.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.host.ResourceHost; +import org.apache.tuscany.spi.host.ResourceResolutionException; +import org.apache.tuscany.spi.wire.InboundWire; + +/** + * Resolves a runtime resource to be injected on a field or method of a Java component type marked with {@link + * org.apache.tuscany.api.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$ $Date$ + */ +public class ResourceObjectFactory implements ObjectFactory { + + private Class type; + private String mappedName; + private CompositeComponent parent; + private ResourceHost host; + private boolean resolveFromHost; + private boolean optional; + + /** + * Instantiates a factory that resolves resources by type + * + * @param type the type of the resource to inject + * @param optional true if an error should be thrown if the resource is not found + * @param parent the parent composite of the component to inject on + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class type, + boolean optional, + CompositeComponent parent, + ResourceHost host) { + this.type = type; + this.parent = parent; + this.host = host; + this.optional = optional; + } + + /** + * Instantiates a factory that resolves resources by mapped name + * + * @param type the type of the resource to inject + * @param mappedName the resource name + * @param optional true if an error should be thrown if the resource is not found + * @param parent the parent composite of the component to inject on + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class type, + String mappedName, + boolean optional, + CompositeComponent parent, + ResourceHost host) { + this.type = type; + this.parent = parent; + this.host = host; + if (mappedName.indexOf("://") >= 0) { + this.resolveFromHost = true; + } + this.mappedName = mappedName; + this.optional = optional; + } + + @SuppressWarnings({"unchecked"}) + public T getInstance() throws ObjectCreationException { + if (resolveFromHost) { + return resolveInstance(); + } else { + T instance = null; + if (mappedName == null) { + try { + InboundWire wire = parent.resolveSystemAutowire(type); + if (wire != null) { + instance = (T) wire.getTargetService(); + } + } catch (TargetResolutionException e) { + throw new ObjectCreationException(e); + } + if (instance == null) { + // if not found in parent scope, search the host namespace + resolveFromHost = true; + instance = resolveInstance(); + } + if (instance == null && !optional) { + throw new ResourceNotFoundException("No resource found matching type", type.getName()); + } + return instance; + } else { + SCAObject child = parent.getSystemChild(mappedName); + if (child instanceof AtomicComponent) { + try { + AtomicComponent component = (AtomicComponent) child; + instance = type.cast(component.getTargetInstance()); + } catch (TargetResolutionException e) { + throw new ObjectCreationException(e); + } + } else if (child != null) { + throw new InvalidResourceTypeException("Invalid resource type", mappedName); + } else if (!optional) { + throw new ResourceNotFoundException("No resource found for URI", mappedName); + } + return instance; + } + } + } + + private T resolveInstance() { + try { + if (mappedName == null) { + return host.resolveResource(type); + } else { + return host.resolveResource(type, mappedName); + } + } catch (ResourceResolutionException e) { + throw new ObjectCreationException(e); + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonListObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonListObjectFactory.java new file mode 100644 index 0000000000..fe503bfd68 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonListObjectFactory.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Implementation of ObjectFactory that returns a single instance, typically an immutable type. + * + * @version $Rev: 430937 $ $Date: 2006-08-12 06:47:56 +0530 (Sat, 12 Aug 2006) $ + */ +public class SingletonListObjectFactory implements ObjectFactory> { + private List instance; + + public SingletonListObjectFactory(List instance) { + this.instance = Collections.unmodifiableList(instance); + } + + public List getInstance() { + return instance; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java new file mode 100644 index 0000000000..713c1ae54f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Implementation of ObjectFactory that returns a single instance, typically an immutable type. + * + * @version $Rev$ $Date$ + */ +public class SingletonObjectFactory implements ObjectFactory { + private final T instance; + + public SingletonObjectFactory(T instance) { + this.instance = instance; + } + + public T getInstance() { + return instance; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java new file mode 100644 index 0000000000..246ef8bdf7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import org.osoa.sca.RequestContext; +import org.osoa.sca.ServiceReference; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.implementation.composite.AbstractCompositeContext; + + +/** + * Default implementation of the {@link org.osoa.sca.CompositeContext} for non-managed code + * + * @version $Rev$ $Date$ + */ +public class CompositeContextImpl extends AbstractCompositeContext { + + public CompositeContextImpl(final CompositeComponent composite, final WireService wireService) { + super(composite, wireService); + } + + public ServiceReference createServiceReferenceForSession(Object arg0) { + throw new UnsupportedOperationException(); + } + + public ServiceReference createServiceReferenceForSession(Object arg0, String arg1) { + throw new UnsupportedOperationException(); + } + + public RequestContext getRequestContext() { + throw new UnsupportedOperationException(); + } + + public ServiceReference newSession(String arg0) { + throw new UnsupportedOperationException(); + } + + public ServiceReference newSession(String arg0, Object arg1) { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java new file mode 100644 index 0000000000..730f29611a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import org.apache.tuscany.api.TuscanyException; + +/** + * Exception indicating that there was a problem launching an application. + * + * @version $Rev$ $Date$ + */ +public abstract class LaunchException extends TuscanyException { + + protected LaunchException(String message) { + super(message); + } + + protected LaunchException(String message, String identifier) { + super(message, identifier); + } + + protected LaunchException(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } + + protected LaunchException(String message, Throwable cause) { + super(message, cause); + } + + protected LaunchException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java new file mode 100644 index 0000000000..6f968b5209 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java @@ -0,0 +1,250 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import javax.xml.stream.XMLInputFactory; + +import org.osoa.sca.CompositeContext; + +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.services.management.TuscanyManagementService; + +import org.apache.tuscany.api.TuscanyException; +import org.apache.tuscany.core.bootstrap.Bootstrapper; +import org.apache.tuscany.core.bootstrap.DefaultBootstrapper; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.host.launcher.Launcher; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.host.RuntimeInfo; +import org.apache.tuscany.host.runtime.InitializationException; +import org.apache.tuscany.host.monitor.FormatterRegistry; + +/** + * Basic launcher implementation. + * + * @version $Rev$ $Date$ + */ +public class LauncherImpl implements Launcher { + /** + * A conventional META-INF based location for the system SCDL. + * + * @see #bootRuntime(URL,MonitorFactory) + */ + public static final String METAINF_SYSTEM_SCDL_PATH = "META-INF/tuscany/system.scdl"; + + /** + * A conventional META-INF based location for the application SCDL. + */ + public static final String METAINF_APPLICATION_SCDL_PATH = "META-INF/sca/default.scdl"; + + private ClassLoader applicationLoader; + + private RuntimeComponent runtime; + + private Deployer deployer; + + private CompositeComponent composite; + + public CompositeContext bootApplication(URL applicationScdl, ClassLoader applicationClassLoader) { + // TODO Auto-generated method stub + return null; + } + + public void bootRuntime(URL systemScdl, ClassLoader systemClassLoader, MonitorFactory monitor) + throws TuscanyException { + if (systemScdl == null) { + throw new LoaderException("Null system SCDL URL"); + } + + XMLInputFactory xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", systemClassLoader); + TuscanyManagementService managementService = null; + Bootstrapper bootstrapper = new DefaultBootstrapper(monitor, xmlFactory, managementService); + Deployer bootDeployer = bootstrapper.createDeployer(); + + // create and start the core runtime + runtime = bootstrapper.createRuntime(); + runtime.start(); + + // initialize the runtime info + CompositeComponent parent = runtime.getSystemComponent(); + RuntimeInfo runtimeInfo = new LauncherRuntimeInfo(getInstallDirectory(), getApplicationRootDirectory(), true); + parent.registerJavaObject("RuntimeInfo", RuntimeInfo.class, runtimeInfo); + + // register the monitor factory + if (monitor instanceof FormatterRegistry) { + List> interfazes = new ArrayList>(2); + interfazes.add(MonitorFactory.class); + interfazes.add(FormatterRegistry.class); + parent.registerJavaObject("MonitorFactory", interfazes, monitor); + } else { + parent.registerJavaObject("MonitorFactory", MonitorFactory.class, monitor); + } + parent.start(); + // create a ComponentDefinition to represent the component we are going to deploy + SystemCompositeImplementation compositeImplementation = new SystemCompositeImplementation(); + compositeImplementation.setScdlLocation(systemScdl); + compositeImplementation.setClassLoader(systemClassLoader); + ComponentDefinition definition = + new ComponentDefinition( + ComponentNames.TUSCANY_SYSTEM, compositeImplementation); + try { + // deploy the component into the runtime under the system parent + composite = (CompositeComponent) bootDeployer.deploy(parent, definition); + } catch (TuscanyException e) { + e.addContextName(definition.getName()); + throw e; + } + // start the system + composite.start(); + + SCAObject child = composite.getSystemChild(ComponentNames.TUSCANY_DEPLOYER); + if (!(child instanceof AtomicComponent)) { + throw new InitializationException("Deployer must be an atomic component"); + } + deployer = (Deployer) ((AtomicComponent) child).getTargetInstance(); + runtime.getRootComponent().start(); + } + + /** + * Shuts down the active runtime being managed by this instance. + */ + public void shutdownRuntime() { + if (composite != null) { + composite.stop(); + composite = null; + } + + if (runtime != null) { + runtime.stop(); + runtime = null; + } + } + + /** + * Returns the classloader for application classes. + * + * @return the classloader for application classes + */ + public ClassLoader getApplicationLoader() { + return applicationLoader; + } + + /** + * Set the classloader to be used for application classes. You should almost always supply your own application + * classloader, based on the hosting environment that the runtime is embedded in. + * + * @param applicationLoader the classloader to be used for application classes + */ + public void setApplicationLoader(ClassLoader applicationLoader) { + this.applicationLoader = applicationLoader; + } + + /** + * Boots the runtime defined by the specified SCDL. + * + * @param systemScdl a resource path to the SCDL defining the system. + * @return a CompositeComponent for the newly booted runtime system + * @throws LoaderException + */ + @Deprecated + public CompositeComponent bootRuntime(URL systemScdl, MonitorFactory monitor) throws TuscanyException { + ClassLoader systemClassLoader = getClass().getClassLoader(); + bootRuntime(systemScdl, systemClassLoader, monitor); + return composite; + } + + /** + * Boots the application defined by the specified SCDL. + * + * @param name the name of the application component + * @param appScdl URL to the SCDL defining the application + * @return a CompositeComponent for the newly booted application + * @throws LoaderException + */ + @Deprecated + public CompositeComponent bootApplication(String name, URL appScdl) throws TuscanyException { + ClassLoader applicationLoader = getApplicationLoader(); + + if (appScdl == null) { + throw new LoaderException("No application scdl found"); + } + + // create a ComponentDefinition to represent the component we are going to deploy + CompositeImplementation impl = new CompositeImplementation(); + impl.setScdlLocation(appScdl); + impl.setClassLoader(applicationLoader); + ComponentDefinition definition = + new ComponentDefinition(name, impl); + + // deploy the component into the runtime under the system parent + CompositeComponent parent = runtime.getRootComponent(); + // FIXME andyp -- this seems bogus when running inside an appserver + ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + + try { + + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + return (CompositeComponent) deployer.deploy(parent, definition); + } finally { + Thread.currentThread().setContextClassLoader(ccl); + } + } + + public File getInstallDirectory() { + String property = System.getProperty("tuscany.installDir"); + if (property != null) { + return new File(property); + } + + // TODO: TUSCANY-648, should this throw an exception if it not running from a jar? + + URL url = getClass().getResource("LauncherImpl.class"); + String jarLocation = url.toString(); + if ("jar".equals(url.getProtocol())) { + jarLocation = jarLocation.substring(4, jarLocation.lastIndexOf("!/")); + } + if (jarLocation.startsWith("file:")) { + jarLocation = jarLocation.substring(5); + } + + File jarFile = new File(jarLocation); + return jarFile.getParentFile().getParentFile(); + } + + public File getApplicationRootDirectory() { + String property = System.getProperty("tuscany.applicationRootDir"); + if (property != null) { + return new File(property); + } + + return new File(System.getProperty("user.dir")); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java new file mode 100644 index 0000000000..a46631508b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URI; + +import org.apache.tuscany.host.RuntimeInfo; + +/** + * @version $Rev$ $Date$ + */ +public class LauncherRuntimeInfo implements RuntimeInfo { + + /** Install directory */ + private final File installDirectory; + + /** Application root directory */ + private final File applicationRootDirectory; + + private final boolean online; + + /** + * Initializes the installation and application root directories. + * + * @param installDirectory Installation directory. + * @param applicationRootDirectory Application root directory. + */ + public LauncherRuntimeInfo(File installDirectory, File applicationRootDirectory, boolean online) { + this.installDirectory = installDirectory; + this.applicationRootDirectory = applicationRootDirectory; + this.online = online; + } + + public URI getDomain() { + throw new UnsupportedOperationException(); + } + + /** + * Return the directory where the running runtime was installed. + * + * @return the directory where the runtime was installed + */ + public File getInstallDirectory() { + return installDirectory; + } + + /** + * Return the root directory used to resolve application file paths. + * + * @return the directory used to resolve application file paths. + */ + public File getApplicationRootDirectory() { + return applicationRootDirectory; + } + + /** + * Gets the base URL for the runtime. + * + * @return The base URL for the runtime. + */ + public URL getBaseURL() { + try { + return installDirectory.toURL(); + } catch (MalformedURLException e) { + // TODO Decide on how to handle the exception + throw new RuntimeException(e); + } + } + + public boolean isOnline() { + return online; + } + + public String getRuntimeId() { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java new file mode 100644 index 0000000000..796ec2b77e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java @@ -0,0 +1,524 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import static org.osoa.sca.Constants.SCA_NS; + +import java.lang.reflect.Type; +import java.net.URI; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.binding.local.LocalBindingDefinition; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.util.ReferenceLoaderHelper; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidReferenceException; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.MissingImplementationException; +import org.apache.tuscany.spi.loader.MissingPropertyValueException; +import org.apache.tuscany.spi.loader.MissingReferenceException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.loader.ReferenceMultiplicityOverridingException; +import org.apache.tuscany.spi.loader.ReferenceMultiplicityViolationException; +import org.apache.tuscany.spi.loader.UndefinedPropertyException; +import org.apache.tuscany.spi.loader.UndefinedReferenceException; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.BindingDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentReferenceDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ComponentTypeReferenceDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.util.stax.StaxUtil; +import org.osoa.sca.annotations.Constructor; +import org.w3c.dom.Element; + +/** + * Loads a component definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class ComponentLoader extends LoaderExtension> { + private static final QName COMPONENT = new QName(SCA_NS, "component"); + + private static final QName PROPERTY = new QName(SCA_NS, "property"); + + private static final QName REFERENCE = new QName(SCA_NS, "reference"); + + private static final String COMPONENT_NAME_ATTR = "name"; + + private static final String COMPONENT_INIT_ATTR = "initLevel"; + + private static final String AUTOWIRE_ATTR = "autowire"; + + private static final String PROPERTY_FILE_ATTR = "file"; + + private static final String PROPERTY_SOURCE_ATTR = "source"; + + private static final String PROPERTY_NAME_ATTR = "name"; + + private static final String PROPERTY_TYPE_ATTR = "type"; + + private static final String PROPERTY_ELEMENT_ATTR = "element"; + + public static final String REF_NAME_ATTR = "name"; + + public static final String REF_MULTIPLICITY_ATTR = "multiplicity"; + + public static final String REF_TARGET_ATTR = "target"; + + public static final char COLON = ':'; + + private PropertyObjectFactory propertyFactory; + + @Constructor + public ComponentLoader(@Autowire + LoaderRegistry registry, @Autowire + PropertyObjectFactory propertyFactory) { + super(registry); + this.propertyFactory = propertyFactory; + } + + public QName getXMLType() { + return COMPONENT; + } + + @SuppressWarnings("unchecked") + public ComponentDefinition load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, + LoaderException { + assert COMPONENT.equals(reader.getName()); + String name = reader.getAttributeValue(null, COMPONENT_NAME_ATTR); + String initLevel = reader.getAttributeValue(null, COMPONENT_INIT_ATTR); + String autowire = reader.getAttributeValue(null, AUTOWIRE_ATTR); + + try { + Implementation impl = loadImplementation(parent, reader, deploymentContext); + registry.loadComponentType(parent, impl, deploymentContext); + + ComponentDefinition> componentDefinition = + new ComponentDefinition>(name, impl); + if (autowire != null) { + componentDefinition.setAutowire(Boolean.parseBoolean(autowire)); + } else { + if (object instanceof CompositeComponentType) { + componentDefinition.setAutowire(((CompositeComponentType)object).isAutowire()); + } + } + + if (initLevel != null) { + if (initLevel.length() == 0) { + componentDefinition.setInitLevel(0); + } else { + try { + componentDefinition.setInitLevel(Integer.valueOf(initLevel)); + } catch (NumberFormatException e) { + throw new InvalidValueException(initLevel, "initValue", e); + } + } + } + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (PROPERTY.equals(qname)) { + loadProperty(reader, deploymentContext, componentDefinition); + } else if (REFERENCE.equals(qname)) { + loadReference(parent, reader, deploymentContext, componentDefinition); + } else { + throw new UnrecognizedElementException(qname); + } + //reader.next(); + break; + case END_ELEMENT: + if (reader.getName().equals(COMPONENT)) { + // hack to leave alone SystemImplementation + if (!((Implementation)componentDefinition.getImplementation() instanceof SystemImplementation)) { + populatePropertyValues(componentDefinition); + } + populateReferences(componentDefinition); + /*ComponentType> type = + (ComponentType>)componentDefinition + .getImplementation().getComponentType(); + for (ReferenceDefinition ref : type.getReferences().values()) { + if (ref.isAutowire()) { + ReferenceTarget referenceTarget = new ReferenceTarget(); + referenceTarget.setReferenceName(ref.getName()); + componentDefinition.add(referenceTarget); + } + }*/ + //validate(componentDefinition); + return componentDefinition; + } + break; + } + } + } catch (LoaderException e) { + e.addContextName(name); + throw e; + } + } + + protected Implementation loadImplementation(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, + LoaderException { + reader.nextTag(); + ModelObject o = registry.load(parent, null, reader, deploymentContext); + if (!(o instanceof Implementation)) { + throw new MissingImplementationException(); + } + return (Implementation)o; + } + + @SuppressWarnings("unchecked") + protected void loadProperty(XMLStreamReader reader, + DeploymentContext deploymentContext, + ComponentDefinition componentDefinition) throws XMLStreamException, + LoaderException { + String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR); + Implementation implementation = componentDefinition.getImplementation(); + ComponentType componentType = implementation.getComponentType(); + Property property = componentType.getProperty(name); + if (property == null) { + throw new UndefinedPropertyException(name); + } + + PropertyValue propertyValue; + readPropertyType(reader, property); + + String source = reader.getAttributeValue(null, PROPERTY_SOURCE_ATTR); + String file = reader.getAttributeValue(null, PROPERTY_FILE_ATTR); + + if (source != null || file != null) { + propertyValue = new PropertyValue(name, source, file); + propertyValue.setValue(property.getDefaultValues()); + LoaderUtil.skipToEndElement(reader); + } else { + try { + DocumentBuilder documentBuilder = DOMHelper.newDocumentBuilder(); + List values = + StaxUtil.createPropertyValues(reader, property.getXmlType(), property + .getXmlElement(), property.isMany(), documentBuilder); + propertyValue = new PropertyValue(name, values); + if (!property.isMany() && values.size() > 1) { + ManyPropertyValueLoaderException ex = new ManyPropertyValueLoaderException(); + ex.setPropertyName(name); + ex.setLine(reader.getLocation().getLineNumber()); + ex.setColumn(reader.getLocation().getColumnNumber()); + throw ex; + } + } catch (ParserConfigurationException e) { + throw new LoaderException(e); + } + } + + ObjectFactory objectFactory = null; + if (property.isMany()) { + objectFactory = propertyFactory.createListObjectFactory(property, propertyValue); + } else { + objectFactory = propertyFactory.createObjectFactory(property, propertyValue); + } + // propertyValue.setValueFactory(new + // SimplePropertyObjectFactory(property, propertyValue.getValue())); + propertyValue.setValueFactory(objectFactory); + componentDefinition.add(propertyValue); + } + + @SuppressWarnings("unchecked") + protected void loadReference(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext, + ComponentDefinition componentDefinition) throws XMLStreamException, + LoaderException { + + ComponentReferenceDefinition componentReference = null; + Implementation impl = componentDefinition.getImplementation(); + ComponentType componentType = + impl.getComponentType(); + + String name = reader.getAttributeValue(null, REF_NAME_ATTR); + + if (name == null) { + throw new InvalidReferenceException("No name specified"); + } else if (!componentType.getReferences().containsKey(name)) { + throw new UndefinedReferenceException(name); + } else { + componentReference = + new ComponentReferenceDefinition(componentType.getReferences().get(name)); + } + + String multiplicityVal = reader.getAttributeValue(null, REF_MULTIPLICITY_ATTR); + Multiplicity multiplicity = + StaxUtil.multiplicity(multiplicityVal, componentType.getReferences().get(name) + .getMultiplicity()); + if (!ReferenceLoaderHelper.isValidMultiplicityOverride(componentType.getReferences() + .get(name).getMultiplicity(), multiplicity)) { + throw new ReferenceMultiplicityOverridingException(name, componentType.getReferences() + .get(name).getMultiplicity(), multiplicity); + } else { + componentReference.setMultiplicity(multiplicity); + } + + String autowire = reader.getAttributeValue(null, AUTOWIRE_ATTR); + if (autowire == null) { + componentReference.setAutowire(componentDefinition.isAutowire()); + } else { + componentReference.setAutowire(Boolean.parseBoolean(autowire)); + } + + String targets = reader.getAttributeValue(null, REF_TARGET_ATTR); + if (targets != null && targets.length() > 0) { + ReferenceLoaderHelper.populateRefTargets(componentReference, targets); + /*if (!ReferenceLoaderHelper.validateMultiplicityAndTargets(multiplicity, + componentReference + .getTargets())) { + throw new ReferenceMultiplicityViolationException(name, + multiplicity, + componentReference + .getTargets().size()); + }*/ + } + + ComponentTypeReferenceDefinition ctReference = componentType.getReferences().get(name); + boolean isBindingsOverriden = false; + while (true) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, null, reader, deploymentContext); + if (o instanceof ServiceContract) { + ServiceContract overridenSvcContract = (ServiceContract)o; + ServiceContract implSvcContract = ctReference.getServiceContract(); + //TODO : Since the JavaInterfaceProcessorRegistryImpl does not do a deep introspection + //this comparison is not possible. This will be uncommented once that is fixed. + /*ReferenceLoaderHelper.checkInterfaceCompatibility(implSvcContract, + overridenSvcContract, + false);*/ + componentReference.setServiceContract(overridenSvcContract); + } else if (o instanceof BindingDefinition) { + componentReference.addBinding((BindingDefinition)o); + isBindingsOverriden = true; + } else { + throw new UnrecognizedElementException(reader.getName()); + } + //reader.next(); + break; + case END_ELEMENT: + if (REFERENCE.equals(reader.getName())) { + if (componentType instanceof CompositeComponentType) { + //AbstractReferenceDefinition definition = componentType.getReferences().get(name); + //if there were targets overridden, then its better to copy the componentType + //bindings from the underlying componentType and set the overriden target + if (targets != null && targets.length() > 0) { + if (componentReference.getBindings().isEmpty()) { + for (URI targetUri : componentReference.getTargets()) { + // TODO JFM allow selection of a default binding + LocalBindingDefinition binding = + new LocalBindingDefinition(targetUri); + componentReference.addBinding(binding); + //HACK [svkrish]: to get composite implementations working.. not sure + //why the componentType should be updated for bindings and targets + componentReference.getAssociatedCompTypeRefDefn() + .addBinding(binding); + } + } else { + for (URI targetUri : componentReference.getTargets()) { + if (isBindingsOverriden) { + for (BindingDefinition binding : componentReference + .getBindings()) { + binding.setTargetUri(targetUri); + } + } else { + BindingDefinition clone = null; + for (BindingDefinition binding : componentReference + .getAssociatedCompTypeRefDefn().getBindings()) { + clone = (BindingDefinition)binding.clone(); + clone.setTargetUri(targetUri); + componentReference.addBinding(clone); + //HACK [svkrish]: to get composite implementations working.. not sure + //why the componentType should be updated for bindings and targets + binding.setTargetUri(targetUri); + } + } + } + } + } + } + componentDefinition.add(componentReference); + return; + } + } + } + } + + @SuppressWarnings("unchecked") + protected void populatePropertyValues(ComponentDefinition> componentDefinition) throws LoaderException, + MissingPropertyValueException { + ComponentType componentType = componentDefinition.getImplementation().getComponentType(); + if (componentType != null) { + Map> properties = componentType.getProperties(); + Map> propertyValues = componentDefinition.getPropertyValues(); + + for (Property aProperty : properties.values()) { + if (propertyValues.get(aProperty.getName()) == null) { + if (aProperty.isMustSupply()) { + throw new MissingPropertyValueException(aProperty.getName()); + } else if (aProperty.getDefaultValues() != null) { + PropertyValue propertyValue = new PropertyValue(); + propertyValue.setName(aProperty.getName()); + propertyValue.setValue(aProperty.getDefaultValues()); + propertyValue.setValueFactory(propertyFactory + .createObjectFactory(aProperty, propertyValue)); + /* + * propertyValue.setValueFactory(new SimplePropertyObjectFactory(aProperty, + * propertyValue.getValue())); + */ + propertyValues.put(aProperty.getName(), propertyValue); + } + } + } + } + } + + private void readPropertyType(XMLStreamReader reader, Property property) throws MissingTypePropertyLoaderException { + + String typeName = reader.getAttributeValue(null, PROPERTY_TYPE_ATTR); + String elementName = reader.getAttributeValue(null, PROPERTY_ELEMENT_ATTR); + QName xmlElement = null; + QName xmlType = null; + + if (typeName != null) { + int index = typeName.indexOf(COLON); + if (index != -1) { + String prefix = typeName.substring(0, index); + String localName = typeName.substring(index + 1); + String ns = reader.getNamespaceURI(prefix); + xmlType = new QName(ns, localName, prefix); + } + } else if (elementName != null) { + int index = elementName.indexOf(COLON); + if (index != -1) { + String prefix = elementName.substring(0, index); + String localName = elementName.substring(index + 1); + String ns = reader.getNamespaceURI(prefix); + xmlElement = new QName(ns, localName, prefix); + // FIXME : + // need to figure out how to determine the xmltype from this + // xmlelement + // this need access to the global xml element thro + // schemalocation or thro + // artifact repository + xmlType = null; + } + } + + if (xmlType != null) { + property.setXmlType(xmlType); + } + + if (xmlElement != null) { + property.setXmlElement(xmlElement); + } + } + + @SuppressWarnings("unchecked") + protected void populateReferences(ComponentDefinition> componentDefinition) { + //bring the component definition in sync with the componenttype for reference definitions + ComponentType> componentType = + componentDefinition.getImplementation().getComponentType(); + + for (ComponentTypeReferenceDefinition refDefn : componentType.getReferences().values()) { + if (componentDefinition.getReferences().get(refDefn.getName()) == null) { + componentDefinition.add(new ComponentReferenceDefinition(refDefn)); + } + } + } + + /** + * Validates a component definition, ensuring all component type configuration elements are satisfied + */ + protected void validate(ComponentDefinition> definition) throws LoaderException { + // validate refererences + Implementation implementation = definition.getImplementation(); + ComponentType type = implementation.getComponentType(); + if (type == null) { + return; + } + for (ComponentReferenceDefinition referenceDef : definition.getReferences().values()) { + if (referenceDef.isAutowire()) { + continue; + } + String name = referenceDef.getName(); + List targets = definition.getReferences().get(name).getTargets(); + if (targets == null) { + throw new MissingReferenceException(name); + } + int count = targets.size(); + Multiplicity multiplicity = referenceDef.getMultiplicity(); + switch (multiplicity) { + case ZERO_N: + break; + case ZERO_ONE: + if (count > 1) { + throw new ReferenceMultiplicityViolationException(name, multiplicity, count); + } + break; + case ONE_ONE: + if (count != 1) { + throw new ReferenceMultiplicityViolationException(name, multiplicity, count); + } + break; + case ONE_N: + if (count < 1) { + throw new ReferenceMultiplicityViolationException(name, multiplicity, count); + } + break; + } + + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java new file mode 100644 index 0000000000..5313f32aa1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import static org.osoa.sca.Constants.SCA_NS; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ComponentTypeReferenceDefinition; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.osoa.sca.annotations.Constructor; + +/** + * @version $Rev$ $Date$ + */ +public class ComponentTypeElementLoader extends LoaderExtension { + public static final QName COMPONENT_TYPE = new QName(SCA_NS, "componentType"); + + @Constructor + public ComponentTypeElementLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return COMPONENT_TYPE; + } + + @SuppressWarnings("unchecked") + public ComponentType load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert COMPONENT_TYPE.equals(reader.getName()); + ComponentType> componentType; + if (object != null) { + assert object instanceof ComponentType; + // a specialized component type was passed in + componentType = (ComponentType>) object; + } else { + componentType = new ComponentType>(); + } + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, componentType, reader, deploymentContext); + if (o instanceof ServiceDefinition) { + componentType.add((ServiceDefinition) o); + } else if (o instanceof ComponentTypeReferenceDefinition) { + componentType.add((ComponentTypeReferenceDefinition) o); + } else if (o instanceof Property) { + componentType.add((Property) o); + } + break; + case END_ELEMENT: + return componentType; + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DefaultPropertyValueLoaderException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DefaultPropertyValueLoaderException.java new file mode 100644 index 0000000000..adcde47dda --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DefaultPropertyValueLoaderException.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + + +/** + * Root unchecked exception for the injection package + * + * @version $Rev: 487057 $ $Date: 2006-12-14 12:50:44 +0530 (Thu, 14 Dec 2006) $ + */ +public class DefaultPropertyValueLoaderException extends PropertyLoaderException { + + public DefaultPropertyValueLoaderException() { + super("Default Property Value must be supplied only when 'mustSupply' attribute is set to 'false'"); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java new file mode 100644 index 0000000000..66aafb6525 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/DependencyLoader.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.services.artifact.Artifact; + +import org.apache.tuscany.core.implementation.composite.Dependency; + +/** + * Loader for handling elements. + * + * @version $Rev$ $Date$ + */ +public class DependencyLoader extends LoaderExtension { + private static final String NS = "http://tuscany.apache.org/xmlns/1.0-SNAPSHOT"; + private static final QName DEPENDENCY = new QName(NS, "dependency"); + private static final QName GROUP = new QName(NS, "group"); + private static final QName NAME = new QName(NS, "name"); + private static final QName VERSION = new QName(NS, "version"); + private static final QName CLASSIFIER = new QName(NS, "classifier"); + private static final QName TYPE = new QName(NS, "type"); + + public DependencyLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return DEPENDENCY; + } + + public Dependency load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + Artifact artifact = new Artifact(); + while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) { + QName name = reader.getName(); + String text = reader.getElementText(); + if (GROUP.equals(name)) { + artifact.setGroup(text); + } else if (NAME.equals(name)) { + artifact.setName(text); + } else if (VERSION.equals(name)) { + artifact.setVersion(text); + } else if (CLASSIFIER.equals(name)) { + artifact.setClassifier(text); + } else if (TYPE.equals(name)) { + artifact.setType(text); + } else { + throw new UnrecognizedElementException(name); + } + } + Dependency dependency = new Dependency(); + dependency.setArtifact(artifact); + return dependency; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java new file mode 100644 index 0000000000..c1de002936 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.net.MalformedURLException; +import java.net.URL; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.MissingIncludeException; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Include; +import org.apache.tuscany.spi.model.ModelObject; + +import org.apache.tuscany.core.deployer.ChildDeploymentContext; + +/** + * Loader that handles <include> elements. + * + * @version $Rev$ $Date$ + */ +public class IncludeLoader extends LoaderExtension { + private static final QName INCLUDE = new QName(SCA_NS, "include"); + + @Constructor({"registry"}) + public IncludeLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return INCLUDE; + } + + public Include load(CompositeComponent parent, ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + assert INCLUDE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String scdlLocation = reader.getAttributeValue(null, "scdlLocation"); + String scdlResource = reader.getAttributeValue(null, "scdlResource"); + LoaderUtil.skipToEndElement(reader); + + ClassLoader cl = deploymentContext.getClassLoader(); + URL url; + if (scdlLocation != null) { + try { + url = new URL(deploymentContext.getScdlLocation(), scdlLocation); + } catch (MalformedURLException e) { + throw new MissingResourceException(scdlLocation, name, e); + } + } else if (scdlResource != null) { + url = cl.getResource(scdlResource); + if (url == null) { + throw new MissingResourceException(scdlResource, name); + } + } else { + throw new MissingIncludeException("No SCDL location or resource specified", name); + } + + DeploymentContext childContext = new ChildDeploymentContext(deploymentContext, cl, url); + CompositeComponentType composite; + try { + composite = loadFromSidefile(parent, url, childContext); + } catch (LoaderException e) { + e.addContextName(name); + throw e; + } + + Include include = new Include(); + include.setName(name); + include.setScdlLocation(url); + include.setIncluded(composite); + return include; + } + + protected CompositeComponentType loadFromSidefile(CompositeComponent parent, + URL url, + DeploymentContext deploymentContext) + throws LoaderException { + return registry.load(parent, null, url, CompositeComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java new file mode 100644 index 0000000000..32678a6179 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.util.ArrayList; +import java.util.List; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; + +import org.apache.tuscany.core.injection.JNDIListObjectFactory; +import org.apache.tuscany.core.injection.JNDIObjectFactory; + +/** + * A StAXPropertyFactory that creates property values by looking them up in the default JNDI InitialContext.

      This + * can be used to locate resources in a J2EE environment and inject them as configuration properties. For example, to + * access a database a component could write: &at;Property DataSource myDB; and configure with + * <properties> <v:myDb>java:comp/env/jdbc/MyDatabase</v:myDB> </properties> + * + * @version $Rev$ $Date$ + */ +public class JNDIPropertyFactory implements PropertyObjectFactory { + public ObjectFactory createObjectFactory(Property property, PropertyValue value) + throws LoaderException { + String text = value.getValue().get(0).getTextContent(); + try { + Context context = new InitialContext(); + return new JNDIObjectFactory(context, text); + } catch (NamingException e) { + throw new LoaderException(e); + } + } + + public ObjectFactory> createListObjectFactory(Property property, PropertyValue value) + throws LoaderException { + try { + List instances = new ArrayList(); + Context context = new InitialContext(); + List text = new ArrayList(); + for (int count = 0 ; count < instances.size() ; ++count) { + text.add(value.getValue().get(count).getTextContent()); + } + return new JNDIListObjectFactory(context, text); + } catch (NamingException e) { + throw new LoaderException(e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java new file mode 100644 index 0000000000..4fad10c95f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderExceptionFormatter.java @@ -0,0 +1,50 @@ +package org.apache.tuscany.core.loader; + +import java.io.PrintWriter; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.loader.LoaderException; + +import org.apache.tuscany.host.monitor.ExceptionFormatter; +import org.apache.tuscany.host.monitor.FormatterRegistry; + +/** + * Formats {@link org.apache.tuscany.spi.loader.LoaderException} events + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class LoaderExceptionFormatter implements ExceptionFormatter { + private FormatterRegistry factory; + + public LoaderExceptionFormatter(@Autowire FormatterRegistry factory) { + this.factory = factory; + factory.register(this); + } + + public boolean canFormat(Class type) { + return LoaderException.class.isAssignableFrom(type); + } + + @Destroy + public void destroy() { + factory.unregister(this); + } + + public PrintWriter write(PrintWriter writer, Throwable exception) { + assert exception instanceof LoaderException; + LoaderException e = (LoaderException) exception; + e.appendBaseMessage(writer); + if (e.getLine() != LoaderException.UNDEFINED) { + writer.write("\nLine: " + e.getLine() + "\n"); + writer.write("Column: " + e.getColumn()); + } else { + writer.write("\n"); + } + e.appendContextStack(writer).append("\n"); + return writer; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java new file mode 100644 index 0000000000..69c182cb6d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.ComponentTypeLoader; +import org.apache.tuscany.spi.loader.InvalidConfigurationException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.StAXElementLoader; +import org.apache.tuscany.spi.loader.UnrecognizedComponentTypeException; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ModelObject; + +/** + * The default implementation of a loader registry + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class LoaderRegistryImpl implements LoaderRegistry { + private Monitor monitor; + private final Map> loaders = + new HashMap>(); + private final Map>, + ComponentTypeLoader>> componentTypeLoaders = + new HashMap>, ComponentTypeLoader>>(); + + public LoaderRegistryImpl(@org.apache.tuscany.api.annotation.Monitor Monitor monitor) { + this.monitor = monitor; + } + + public void registerLoader(QName element, StAXElementLoader loader) { + monitor.registeringLoader(element); + loaders.put(element, loader); + } + + public void unregisterLoader(QName element, StAXElementLoader loader) { + monitor.unregisteringLoader(element); + loaders.remove(element); + } + + public ModelObject load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + QName name = reader.getName(); + monitor.elementLoad(name); + StAXElementLoader loader = loaders.get(name); + if (loader == null) { + throw new UnrecognizedElementException(name); + } + return loader.load(parent, object, reader, deploymentContext); + } + + public MO load(CompositeComponent parent, + ModelObject object, + URL url, + Class type, + DeploymentContext ctx) throws LoaderException { + try { + XMLStreamReader reader; + InputStream is; + is = url.openStream(); + try { + XMLInputFactory factory = ctx.getXmlFactory(); + reader = factory.createXMLStreamReader(is); + try { + reader.nextTag(); + QName name = reader.getName(); + ModelObject mo = load(parent, object, reader, ctx); + if (type.isInstance(mo)) { + return type.cast(mo); + } else { + UnrecognizedElementException e = new UnrecognizedElementException(name); + e.setResourceURI(url.toString()); + throw e; + } + } catch (LoaderException e) { + Location location = reader.getLocation(); + e.setLine(location.getLineNumber()); + e.setColumn(location.getColumnNumber()); + throw e; + } finally { + try { + reader.close(); + } catch (XMLStreamException e) { + // ignore + } + } + } finally { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } catch (IOException e) { + LoaderException sfe = new LoaderException(e); + sfe.setResourceURI(url.toString()); + throw sfe; + } catch (XMLStreamException e) { + throw new InvalidConfigurationException("Invalid or missing resource", url.toString(), e); + } + } + + public > void registerLoader(Class key, ComponentTypeLoader loader) { + componentTypeLoaders.put(key, loader); + } + + public > void unregisterLoader(Class key) { + componentTypeLoaders.remove(key); + } + + @SuppressWarnings("unchecked") + public > void loadComponentType(CompositeComponent parent, + I implementation, + DeploymentContext deploymentContext) + throws LoaderException { + Class key = (Class) implementation.getClass(); + ComponentTypeLoader loader = (ComponentTypeLoader) componentTypeLoaders.get(key); + if (loader == null) { + throw new UnrecognizedComponentTypeException(key); + } + try { + loader.load(parent, implementation, deploymentContext); + } catch ( Exception e) { + e.printStackTrace(); + } + } + + public static interface Monitor { + /** + * Event emitted when a StAX element loader is registered. + * + * @param xmlType the QName of the element the loader will handle + */ + void registeringLoader(QName xmlType); + + /** + * Event emitted when a StAX element loader is unregistered. + * + * @param xmlType the QName of the element the loader will handle + */ + void unregisteringLoader(QName xmlType); + + /** + * Event emitted when a request is made to load an element. + * + * @param xmlType the QName of the element that should be loaded + */ + void elementLoad(QName xmlType); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ManyPropertyValueLoaderException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ManyPropertyValueLoaderException.java new file mode 100644 index 0000000000..e0893994a8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ManyPropertyValueLoaderException.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + + +/** + * Root unchecked exception for the injection package + * + * @version $Rev: 487057 $ $Date: 2006-12-14 12:50:44 +0530 (Thu, 14 Dec 2006) $ + */ +public class ManyPropertyValueLoaderException extends PropertyLoaderException { + + public ManyPropertyValueLoaderException() { + super("Multiple property values may be supplied only if 'many' attribute is set to 'true'"); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/MissingTypePropertyLoaderException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/MissingTypePropertyLoaderException.java new file mode 100644 index 0000000000..9ec0ac2a68 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/MissingTypePropertyLoaderException.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + + +/** + * Root unchecked exception for the injection package + * + * @version $Rev: 487057 $ $Date: 2006-12-14 12:50:44 +0530 (Thu, 14 Dec 2006) $ + */ +public class MissingTypePropertyLoaderException extends PropertyLoaderException { + + public MissingTypePropertyLoaderException() { + super("Property type missing - either one of 'type' or 'element' must be specified "); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java new file mode 100644 index 0000000000..7f9df442e5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PolicySetLoader.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.model.IntentMap; +import org.apache.tuscany.spi.model.IntentName; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.PolicySet; +import org.apache.tuscany.spi.model.PolicySetReference; +import org.apache.tuscany.spi.model.Qualifier; +import org.apache.tuscany.spi.model.WSPolicyAttachment; + +/** + * Loads a PolicySet definition from an SCDL file. + * + * @version $Rev$ $Date$ + */ +public class PolicySetLoader extends LoaderExtension { + + private static final String WSPOLICY_NAMESPACE = "http://schemas.xmlsoap.org/ws/2004/09/policy"; + + private static final QName POLICYSET = new QName(SCA_NS, "policySet"); + + private static final QName INTENTMAP = new QName(SCA_NS, "intentMap"); + + private static final QName QUALIFIER = new QName(SCA_NS, "qualifier"); + + private static final QName POLICYSETREFERENCE = new QName(SCA_NS, "policySetReference"); + + private static final QName WSPOLICYATTACHMENT = new QName(WSPOLICY_NAMESPACE, "PolicyAttachment"); + + @Constructor({"registry"}) + public PolicySetLoader(@Autowire LoaderRegistry registry) { + super(registry); + + } + + @Override + public QName getXMLType() { + return POLICYSET; + } + + public PolicySet load(CompositeComponent parent, ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException { + assert POLICYSET.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String provides = reader.getAttributeValue(null, "provides"); + String appliesTo = reader.getAttributeValue(null, "appliesTo"); + PolicySet policySet = new PolicySet(new QName(SCA_NS, name), parseIntentName(provides)); + String[] appliesToArtifact = split(appliesTo); + for (String artifact : appliesToArtifact) { + policySet.addAppliedArtifacts(new QName(SCA_NS, artifact)); + } + while (true) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (INTENTMAP.equals(qname)) { + policySet.addIntentMap(loadIntentMap(reader, deploymentContext)); + } else if (POLICYSETREFERENCE.equals(qname)) { + policySet.addPolicySetReference(loadPolicyReference(reader, deploymentContext)); + } else if (WSPOLICYATTACHMENT.equals(qname)) { + policySet.addWsPolicyAttachment(loadWSPolicyAttachment(reader, deploymentContext)); + } + + reader.next(); + break; + case END_ELEMENT: + if (reader.getName().equals(POLICYSET)) { + return policySet; + } + break; + } + } + + } + + private PolicySetReference loadPolicyReference(XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException { + assert POLICYSETREFERENCE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + LoaderUtil.skipToEndElement(reader); + return new PolicySetReference(new QName(SCA_NS, name)); + } + + private IntentMap loadIntentMap(XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException { + assert INTENTMAP.equals(reader.getName()); + String defaultIntentAttr = reader.getAttributeValue(null, "default"); + String provides = reader.getAttributeValue(null, "provides"); + IntentMap intentMap = new IntentMap(defaultIntentAttr, java.util.Arrays.asList(split(provides))); + //parentPolicySet.addIntentMap(intentMap); + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (QUALIFIER.equals(qname)) { + intentMap.addQualifier(loadQualifier(reader, deploymentContext)); + } + reader.next(); + break; + case END_ELEMENT: + if (reader.getName().equals(INTENTMAP)) { + return intentMap; + } + } + } + + } + + private Qualifier loadQualifier(XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException { + assert QUALIFIER.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + Qualifier qualifier = new Qualifier(name); + while (true) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (INTENTMAP.equals(qname)) { + qualifier.setIntentMap(loadIntentMap(reader, deploymentContext)); + } else if (WSPOLICYATTACHMENT.equals(qname)) { + qualifier.addWsPolicyAttachment(loadWSPolicyAttachment(reader, deploymentContext)); + } + reader.next(); + break; + case END_ELEMENT: + if (reader.getName().equals(QUALIFIER)) { + return qualifier; + } + } + } + + } + + private WSPolicyAttachment loadWSPolicyAttachment(XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException { + return new WSPolicyAttachment(); + } + + /** + * Split a string to string array separated by " " + */ + private static String[] split(String string) { + if (string == null) { + return new String[0]; + } + String[] intents = string.split("[ ]+"); + return intents; + } + + private static List parseIntentName(String attributes) { + String[] intents = split(attributes); + List result = new ArrayList(intents.length); + for (String intent : intents) { + result.add(new IntentName(intent)); + } + return result; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java new file mode 100644 index 0000000000..41113d1da2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import static org.osoa.sca.Constants.SCA_NS; + +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.util.stax.StaxUtil; +import org.osoa.sca.annotations.Constructor; +import org.w3c.dom.Element; + +/** + * Loads a property from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class PropertyLoader extends LoaderExtension { + public static final String PROPERTY_NAME_ATTR = "name"; + public static final String PROPERTY_TYPE_ATTR = "type"; + public static final String PROPERTY_ELEMENT_ATTR = "element"; + public static final String PROPERTY_MANY_ATTR = "many"; + public static final String PROPERTY_NO_DEFAULT_ATTR = "mustSupply"; + public static final String DEFAULT_PREFIX = "xs"; + public static final String DEFAULT_SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + public static final char COLON = ':'; + + public static final QName PROPERTY = new QName(SCA_NS, "property"); + private final DocumentBuilder documentBuilder; + + @Constructor( {"registry"}) + public PropertyLoader(@Autowire + LoaderRegistry registry) { + super(registry); + try { + documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + } catch (ParserConfigurationException e) { + // we should be able to construct the default DocumentBuilder + throw new AssertionError(e); + } + } + + public QName getXMLType() { + return PROPERTY; + } + + public Property load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext ctx) throws XMLStreamException, + PropertyLoaderException { + assert PROPERTY.equals(reader.getName()); + String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR); + String typeName = reader.getAttributeValue(null, PROPERTY_TYPE_ATTR); + String elementName = reader.getAttributeValue(null, PROPERTY_ELEMENT_ATTR); + QName xmlElement = null; + QName xmlType = null; + + if (typeName != null) { + int index = typeName.indexOf(COLON); + if (index != -1) { + String prefix = typeName.substring(0, index); + if (prefix == null || prefix.length() == 0) { + prefix = DEFAULT_PREFIX; + } + + String localName = typeName.substring(index + 1); + String ns = reader.getNamespaceURI(prefix); + if (ns == null || ns.length() == 0) { + ns = DEFAULT_SCHEMA_NS; + } + xmlType = new QName(ns, localName, prefix); + } + } else if (elementName != null) { + int index = elementName.indexOf(COLON); + if (index != -1) { + String prefix = elementName.substring(0, index); + String localName = elementName.substring(index + 1); + String ns = reader.getNamespaceURI(prefix); + xmlElement = new QName(ns, localName, prefix); + // FIXME : + // need to figure out how to determine the xmltype from this + // xmlelement + // this need access to the global xml element thro + // schemalocation or thro + // artifact repository + xmlType = null; + } + } + + if (xmlType == null && xmlElement == null) { + MissingTypePropertyLoaderException ex = new MissingTypePropertyLoaderException(); + ex.setPropertyName(name); + ex.setLine(reader.getLocation().getLineNumber()); + ex.setColumn(reader.getLocation().getColumnNumber()); + throw ex; + } + + boolean many = false; + boolean mustSupply = false; + String attrValue = null; + attrValue = reader.getAttributeValue(null, PROPERTY_MANY_ATTR); + if (attrValue != null) { + many = Boolean.parseBoolean(attrValue); + } + + attrValue = reader.getAttributeValue(null, PROPERTY_NO_DEFAULT_ATTR); + if (attrValue != null) { + mustSupply = Boolean.parseBoolean(attrValue); + } + + List defaultValues = + StaxUtil.createPropertyValues(reader, xmlType, xmlElement, many, documentBuilder); + + if (mustSupply && defaultValues.size() > 0) { + DefaultPropertyValueLoaderException ex = new DefaultPropertyValueLoaderException(); + ex.setPropertyName(name); + ex.setLine(reader.getLocation().getLineNumber()); + ex.setColumn(reader.getLocation().getColumnNumber()); + throw ex; + } + + if (!many && defaultValues.size() > 1) { + ManyPropertyValueLoaderException ex = new ManyPropertyValueLoaderException(); + ex.setPropertyName(name); + ex.setLine(reader.getLocation().getLineNumber()); + ex.setColumn(reader.getLocation().getColumnNumber()); + throw ex; + } + + Property property = new Property(); + property.setName(name); + property.setXmlType(xmlType); + property.setXmlElement(xmlElement); + property.setMany(many); + property.setMustSupply(mustSupply); + property.setDefaultValues(defaultValues); + return property; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoaderException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoaderException.java new file mode 100644 index 0000000000..9e08396a68 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoaderException.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import org.apache.tuscany.spi.loader.LoaderException; + +/** + * Root unchecked exception for the injection package + * + * @version $Rev: 487057 $ $Date: 2006-12-14 12:50:44 +0530 (Thu, 14 Dec 2006) $ + */ +public class PropertyLoaderException extends LoaderException { + + private String propertyName; + + public PropertyLoaderException() { + super(); + } + + public PropertyLoaderException(String message) { + super(message); + } + + + protected PropertyLoaderException(String message, String identifier) { + super(message, identifier); + } + + public PropertyLoaderException(String message, Throwable cause) { + super(message, cause); + } + + protected PropertyLoaderException(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } + + public PropertyLoaderException(Throwable cause) { + super(cause); + } + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + public String getMessage() { + return super.getMessage() + " in " + getPropertyName(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java new file mode 100644 index 0000000000..37acbcbf55 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import static org.osoa.sca.Constants.SCA_NS; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.util.ReferenceLoaderHelper; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.DuplicateReferenceNameException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.ReferenceMultiplicityViolationException; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.BindingDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ComponentTypeReferenceDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeReferenceDefinition; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.util.stax.StaxUtil; +import org.osoa.sca.annotations.Constructor; + +/** + * Loads a reference from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class ReferenceLoader extends LoaderExtension { + public static final String NAME_ATTR = "name"; + + public static final String MULTIPLICITY_ATTR = "multiplicity"; + + public static final String WIRED_BY_IMPL_ATTR = "wiredByImpl"; + + public static final String TARGET_ATTR = "target"; + + public static final String PROMOTE_ATTR = "promote"; + + public static final QName REFERENCE = new QName(SCA_NS, "reference"); + + @Constructor + public ReferenceLoader(@Autowire + LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return REFERENCE; + } + + public ComponentTypeReferenceDefinition load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + if (object instanceof CompositeComponentType) { + return loadCompositeReference(parent, object, reader, deploymentContext); + //return loadComponentType(parent, object, reader, deploymentContext); + } else { + return loadComponentTypeReference(parent, object, reader, deploymentContext); + } + } + + + + public ComponentTypeReferenceDefinition loadComponentTypeReference(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + + assert REFERENCE.equals(reader.getName()); + String name = reader.getAttributeValue(null, NAME_ATTR); + String multiplicityVal = reader.getAttributeValue(null, MULTIPLICITY_ATTR); + String wiredByImpl = reader.getAttributeValue(null, WIRED_BY_IMPL_ATTR); + String targets = reader.getAttributeValue(null, TARGET_ATTR); + Multiplicity multiplicity = StaxUtil.multiplicity(multiplicityVal, Multiplicity.ONE_ONE); + + + + ComponentType componentType = (ComponentType)object; + if ( componentType.getReferences().get(name) != null) { + throw new DuplicateReferenceNameException(name, + DuplicateReferenceNameException.COMPONENT_TYPE, + ""); + } + ComponentTypeReferenceDefinition referenceDefinition = new ComponentTypeReferenceDefinition(); + referenceDefinition.setName(name); + referenceDefinition.setMultiplicity(multiplicity); + referenceDefinition.setName(name); + referenceDefinition.setWiredByImpl(Boolean.parseBoolean(wiredByImpl)); + + if (targets != null && targets.length() > 0 ) + ReferenceLoaderHelper.populateRefTargets(referenceDefinition, targets); + + /*if (!ReferenceLoaderHelper.validateMultiplicityAndTargets(multiplicity, referenceDefinition + .getTargets())) { + throw new ReferenceMultiplicityViolationException(name, multiplicity, referenceDefinition.getTargets().size()); + }*/ + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, null, reader, deploymentContext); + if (o instanceof ServiceContract) { + referenceDefinition.setServiceContract((ServiceContract)o); + } else if (o instanceof BindingDefinition) { + referenceDefinition.addBinding((BindingDefinition)o); + } else { + throw new UnrecognizedElementException(reader.getName()); + } + break; + case END_ELEMENT: + return referenceDefinition; + } + } + } + + public CompositeReferenceDefinition loadCompositeReference(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + + String name = reader.getAttributeValue(null, NAME_ATTR); + String multiplicityVal = reader.getAttributeValue(null, MULTIPLICITY_ATTR); + String wiredByImpl = reader.getAttributeValue(null, WIRED_BY_IMPL_ATTR); + String targets = reader.getAttributeValue(null, TARGET_ATTR); + String promotedComponentRefs = reader.getAttributeValue(null, PROMOTE_ATTR); + //if multiplicity is not set, it will be derived in the composite loader by looking + //at the multiplicity of all promoted references - which can be done only after the composite + //is completelly loaded + Multiplicity multiplicity = StaxUtil.multiplicity(multiplicityVal, null); + + + CompositeComponentType compositeCompType = (CompositeComponentType)object; + if ( compositeCompType.getDeclaredReferences().get(name) != null) { + throw new DuplicateReferenceNameException(name, + DuplicateReferenceNameException.COMPOSITE, + compositeCompType.getName()); + } + CompositeReferenceDefinition referenceDefinition = new CompositeReferenceDefinition(); + referenceDefinition.setName(name); + referenceDefinition.setMultiplicity(multiplicity); + + if (promotedComponentRefs != null && promotedComponentRefs.length() > 0) { + ReferenceLoaderHelper.populatePromotedRefs(referenceDefinition, promotedComponentRefs); + } + + if (targets != null && targets.length() > 0 ) + ReferenceLoaderHelper.populateRefTargets(referenceDefinition, targets); + + referenceDefinition.setWiredByImpl(Boolean.parseBoolean(wiredByImpl)); + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, null, reader, deploymentContext); + if (o instanceof ServiceContract) { + referenceDefinition.setServiceContract((ServiceContract)o); + } else if (o instanceof BindingDefinition) { + referenceDefinition.addBinding((BindingDefinition)o); + } else { + throw new UnrecognizedElementException(reader.getName()); + } + break; + case END_ELEMENT: + return referenceDefinition; + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java new file mode 100644 index 0000000000..a365a281b5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.net.URI; +import java.net.URISyntaxException; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidReferenceException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.BindingDefinition; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Loads a service definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class ServiceLoader extends LoaderExtension { + private static final QName SERVICE = new QName(SCA_NS, "service"); + private static final QName REFERENCE = new QName(SCA_NS, "reference"); + + @Constructor + public ServiceLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return SERVICE; + } + + public ServiceDefinition load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert SERVICE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String target = null; + ServiceDefinition def = new ServiceDefinition(); + def.setName(name); + while (true) { + int i = reader.next(); + switch (i) { + case START_ELEMENT: + // there is a reference already using this qname which doesn't seem appropriate. + if (REFERENCE.equals(reader.getName())) { + String text = reader.getElementText(); + target = text != null ? text.trim() : null; + } else { + ModelObject o = registry.load(parent, null, reader, deploymentContext); + if (o instanceof ServiceContract) { + def.setServiceContract((ServiceContract) o); + } else if (o instanceof BindingDefinition) { + def.addBinding((BindingDefinition) o); + } else { + throw new UnrecognizedElementException(reader.getName()); + } + } + break; + case END_ELEMENT: + if (SERVICE.equals(reader.getName())) { + if (target != null) { + try { + def.setTarget(new URI(target)); + } catch (URISyntaxException e) { + throw new InvalidReferenceException(target, name); + } + } + return def; + } + break; + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java new file mode 100644 index 0000000000..965dbcf8d5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.stream.XMLStreamException; + +import org.apache.tuscany.core.injection.SingletonListObjectFactory; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; + +/** + * Implementation of StAXPropertyFactory that interprets the XML as + * + * @version $Rev$ $Date$ + */ +public class StringParserPropertyFactory implements PropertyObjectFactory { + + public ObjectFactory createObjectFactory(Property property, PropertyValue value) + throws LoaderException { + String text = value.getValue().get(0).getTextContent(); + return new SingletonObjectFactory(createInstance(text, property.getJavaType())); + } + + public ObjectFactory> createListObjectFactory(Property property, PropertyValue value) + throws LoaderException { + String text = null; + List instances = new ArrayList(); + for (int count = 0 ; count < value.getValue().size() ; ++count) { + text = value.getValue().get(count).getTextContent(); + instances.add(createInstance(text, property.getJavaType())); + } + return new SingletonListObjectFactory(instances); + } + + @SuppressWarnings("unchecked") + public T createInstance(String text, Class type) throws LoaderException { + // Class type = property.getJavaType(); + assert type != null : "property type is null"; + + // degenerate case where property type is a String + if (String.class.equals(type)) { + return type.cast(text); + } + + // special handler to convert hexBinary to a byte[] + if (byte[].class.equals(type)) { + byte[] instance = new byte[text.length() >> 1]; + for (int i = 0; i < instance.length; i++) { + instance[i] = + (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text + .charAt((i << 1) + 1), 16)); + } + return type.cast(instance); + } + + // does this type have a static valueOf(String) method? + try { + Method valueOf = type.getMethod("valueOf", String.class); + if (Modifier.isStatic(valueOf.getModifiers())) { + try { + return type.cast(valueOf.invoke(null, text)); + } catch (IllegalAccessException e) { + throw new AssertionError("getMethod returned an inaccessible method"); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + } + } catch (NoSuchMethodException e) { + // try something else + } + + // does this type have a constructor that takes a String? + try { + Constructor ctr = type.getConstructor(String.class); + return ctr.newInstance(text); + } catch (NoSuchMethodException e) { + // try something else + } catch (IllegalAccessException e) { + throw new AssertionError("getConstructor returned an inaccessible method"); + } catch (InstantiationException e) { + throw new LoaderException("Property type cannot be instantiated: " + type.getName()); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + + // do we have a property editor for it? + PropertyEditor editor = PropertyEditorManager.findEditor(type); + if (editor != null) { + try { + editor.setAsText(text); + return (T) editor.getValue(); + } catch (IllegalArgumentException e) { + // FIXME we should throw something better + throw new LoaderException(e); + + } + } + + // FIXME we should throw something better + throw new LoaderException("Do not have a way to parse a String into a " + type.getName()); + + } + + @SuppressWarnings("unchecked") + public ObjectFactory createObjectFactory(String text, Property property) + throws XMLStreamException, LoaderException { + Class type = property.getJavaType(); + assert type != null : "property type is null"; + + // degenerate case where property type is a String + if (String.class.equals(type)) { + return new SingletonObjectFactory(type.cast(text)); + } + + // special handler to convert hexBinary to a byte[] + if (byte[].class.equals(type)) { + byte[] instance = new byte[text.length() >> 1]; + for (int i = 0; i < instance.length; i++) { + instance[i] = + (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text + .charAt((i << 1) + 1), 16)); + } + return new SingletonObjectFactory(type.cast(instance)); + } + + // does this type have a static valueOf(String) method? + try { + Method valueOf = type.getMethod("valueOf", String.class); + if (Modifier.isStatic(valueOf.getModifiers())) { + try { + return new SingletonObjectFactory(type.cast(valueOf.invoke(null, text))); + } catch (IllegalAccessException e) { + throw new AssertionError("getMethod returned an inaccessible method"); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + } + } catch (NoSuchMethodException e) { + // try something else + } + + // does this type have a constructor that takes a String? + try { + Constructor ctr = type.getConstructor(String.class); + return new SingletonObjectFactory(ctr.newInstance(text)); + } catch (NoSuchMethodException e) { + // try something else + } catch (IllegalAccessException e) { + throw new AssertionError("getConstructor returned an inaccessible method"); + } catch (InstantiationException e) { + throw new LoaderException("Property type cannot be instantiated: " + type.getName()); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + + // do we have a property editor for it? + PropertyEditor editor = PropertyEditorManager.findEditor(type); + if (editor != null) { + try { + editor.setAsText(text); + return new SingletonObjectFactory((T) editor.getValue()); + } catch (IllegalArgumentException e) { + // FIXME we should throw something better + throw new LoaderException(e); + + } + } + + // FIXME we should throw something better + throw new LoaderException("Do not have a way to parse a String into a " + type.getName()); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java new file mode 100644 index 0000000000..c6863ec140 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/WireLoader.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.net.URI; +import java.net.URISyntaxException; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidWireException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.WireDefinition; + +/** + * Loads a wire from an XML-based assembly file + * + * @version $Rev: 465084 $ $Date: 2006-10-18 04:00:49 +0530 (Wed, 18 Oct 2006) $ + */ +public class WireLoader extends LoaderExtension { + private static final QName WIRE = new QName(SCA_NS, "wire"); + private static final QName SOURCE_URI = new QName(SCA_NS, "source.uri"); + private static final QName TARGET_URI = new QName(SCA_NS, "target.uri"); + + @Constructor({"registry"}) + public WireLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return WIRE; + } + + public WireDefinition load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert WIRE.equals(reader.getName()); + WireDefinition wireDefn; + URI sourceURI = null; + URI targetURI = null; + String uriString; + while (true) { + switch (reader.next()) { + case START_ELEMENT: + try { + if (reader.getName().equals(SOURCE_URI)) { + uriString = reader.getElementText(); + if (uriString != null && uriString.trim().length() > 0) { + sourceURI = new URI(uriString); + } else { + throw new InvalidWireException("Wire source not defined"); + } + } else if (reader.getName().equals(TARGET_URI)) { + uriString = reader.getElementText(); + if (uriString != null && uriString.trim().length() > 0) { + targetURI = new URI(uriString); + } else { + throw new InvalidWireException("Wire target not defined"); + } + } else { + QName name = reader.getName(); + throw new InvalidWireException("Unrecognized element in wire ", name.toString()); + } + } catch (URISyntaxException e) { + throw new InvalidWireException("Invalid wire uri", e); + } + + reader.next(); + break; + case END_ELEMENT: + if (reader.getName().equals(WIRE)) { + if (sourceURI != null && targetURI != null) { + wireDefn = new WireDefinition(); + wireDefn.setSource(sourceURI); + wireDefn.setTarget(targetURI); + } else { + throw new InvalidWireException("Incomplete wire definition"); + } + return wireDefn; + } + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/marshaller/ComponentDefinitionMarshaller.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/marshaller/ComponentDefinitionMarshaller.java new file mode 100644 index 0000000000..b1510b67e0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/marshaller/ComponentDefinitionMarshaller.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.marshaller; + +import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.spi.marshaller.MarshalException; +import org.apache.tuscany.spi.marshaller.ModelMarshaller; +import org.apache.tuscany.spi.model.ComponentDefinition; + +/** + * Marshaller used for marshalling and unmarshalling component definition. + * + * @version $Rev$ $Date$ + * + */ +public class ComponentDefinitionMarshaller implements ModelMarshaller> { + + /** + * Marshalls the component definition object to the specified stream writer. + * + * @param modelObject Component definition object to be serialized. + * @param writer Stream writer to which the infoset is serialized. + * @throws MarshalException In case of any marshalling error. + */ + public void marshall(ComponentDefinition modelObject, XMLStreamWriter writer) throws MarshalException { + + try { + writer.writeStartDocument(); + writer.writeEndDocument(); + } catch (XMLStreamException ex) { + throw new MarshalException(ex); + } + + } + + /** + * Unmarshalls the component definition object from an XML stream. + * + * @param reader XML stream from where the marshalled XML is read. + * @param upconvert Whether to upconvert the object is the current runtime + * supports a higher version of the model object. + * @return Hydrated component definition object. + * @throws MarshalException In case of any unmarshalling error. + */ + public ComponentDefinition unmarshall(XMLStreamReader reader, boolean upconvert) throws MarshalException { + try { + while (true) { + ComponentDefinition definition = null; + switch (reader.next()) { + case END_DOCUMENT: + return definition; + } + } + } catch (XMLStreamException ex) { + throw new MarshalException(ex); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java new file mode 100644 index 0000000000..686c74c7f8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/DefaultExceptionFormatter.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import java.io.PrintWriter; + +import org.apache.tuscany.api.TuscanyException; +import org.apache.tuscany.api.TuscanyRuntimeException; +import org.apache.tuscany.host.monitor.ExceptionFormatter; + +/** + * Performs basics formatting of exceptions for JDK logging + * + * @version $Rev$ $Date$ + */ +public class DefaultExceptionFormatter implements ExceptionFormatter { + + public DefaultExceptionFormatter() { + } + + public boolean canFormat(Class type) { + return Throwable.class.isAssignableFrom(type); + } + + public PrintWriter write(PrintWriter writer, Throwable exception) { + if (exception instanceof TuscanyException) { + TuscanyException e = (TuscanyException) exception; + e.appendContextStack(e.appendBaseMessage(writer)); + } else if (exception instanceof TuscanyRuntimeException) { + TuscanyRuntimeException e = (TuscanyRuntimeException) exception; + e.appendContextStack(e.appendBaseMessage(writer)); + } + writer.append("\n"); + return writer; + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java new file mode 100644 index 0000000000..cf07b0f914 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +/** + * Exception indicating an invalid log level has been passed. + * + * @version $Rev$ $Date$ + */ +public class InvalidLevelException extends IllegalArgumentException { + private static final long serialVersionUID = 7767234706427841915L; + private final String method; + private final String level; + + /** + * Constructor specifying the method name and the level affected. + * + * @param method the name of the method being monitored + * @param level the invalid log level value + */ + public InvalidLevelException(String method, String level) { + super(); + this.method = method; + this.level = level; + } + + /** + * Returns the name of the method being monitored. + * + * @return the name of the method being monitored + */ + public String getMethod() { + return method; + } + + /** + * Returns the invalid log level specified. + * + * @return the invalid log level that was specified + */ + public String getLevel() { + return level; + } + + public String getMessage() { + return "Invalid level for method " + method + " : " + level; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java new file mode 100644 index 0000000000..019dcbdcd3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java @@ -0,0 +1,321 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.osoa.sca.annotations.Service; + +import org.apache.tuscany.api.annotation.LogLevel; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.host.monitor.ExceptionFormatter; +import org.apache.tuscany.host.monitor.FormatterRegistry; + +/** + * A factory for monitors that forwards events to a {@link java.util.logging.Logger Java Logging (JSR47) Logger}. + * + * @version $Rev$ $Date$ + * @see java.util.logging + */ +@Service(interfaces = {MonitorFactory.class, FormatterRegistry.class}) +public class JavaLoggingMonitorFactory implements MonitorFactory, FormatterRegistry { + private String bundleName; + private Level defaultLevel; + private Map levels; + private List formatters = new ArrayList(); + private ExceptionFormatter defaultFormatter = new DefaultExceptionFormatter(); + private Map, WeakReference> proxies = new WeakHashMap, WeakReference>(); + + /** + * Construct a MonitorFactory that will monitor the specified methods at the specified levels and generate messages + * using java.util.logging. + *

      + * The supplied Properties can be used to specify custom log levels for specific monitor methods. The key should be + * the method name in form returned by Class.getName() + '#' + Method.getName() and the value the log + * level to use as defined by {@link java.util.logging.Level}. + * + * @param levels definition of custom levels for specific monitored methods, may be null or empty. + * @param defaultLevel the default log level to use + * @param bundleName the name of a resource bundle that will be passed to the logger + * @see java.util.logging.Logger + */ + public JavaLoggingMonitorFactory(Properties levels, Level defaultLevel, String bundleName) { + Map configProperties = new HashMap(); + configProperties.put("levels", levels); + configProperties.put("defaultLevel", defaultLevel); + configProperties.put("bundleName", bundleName); + initInternal(configProperties); + } + + /** + * Constructs a MonitorFactory that needs to be subsequently configured via a call to {@link #initialize}. + */ + public JavaLoggingMonitorFactory() { + } + + public void initialize(Map configProperties) { + if (configProperties == null) { + return; + } + initInternal(configProperties); + } + + private void initInternal(Map configProperties) { + try { + this.defaultLevel = (Level) configProperties.get("defaultLevel"); + this.bundleName = (String) configProperties.get("bundleName"); + Properties levels = (Properties) configProperties.get("levels"); + + this.levels = new HashMap(); + if (levels != null) { + for (Map.Entry entry : levels.entrySet()) { + String method = (String) entry.getKey(); + String level = (String) entry.getValue(); + try { + this.levels.put(method, Level.parse(level)); + } catch (IllegalArgumentException e) { + throw new InvalidLevelException(method, level); + } + } + } + } catch (ClassCastException cce) { + throw new IllegalArgumentException(cce.getLocalizedMessage()); + } + } + + public synchronized T getMonitor(Class monitorInterface) { + T proxy = getCachedMonitor(monitorInterface); + if (proxy == null) { + proxy = createMonitor(monitorInterface, bundleName); + proxies.put(monitorInterface, new WeakReference(proxy)); + } + return proxy; + } + + private T getCachedMonitor(Class monitorInterface) { + WeakReference ref = proxies.get(monitorInterface); + return (ref != null) ? monitorInterface.cast(ref.get()) : null; + } + + private T createMonitor(Class monitorInterface, String bundleName) { + String className = monitorInterface.getName(); + Logger logger = Logger.getLogger(className); + Method[] methods = monitorInterface.getMethods(); + Map levels = new HashMap(methods.length); + for (Method method : methods) { + String key = className + '#' + method.getName(); + Level level = null; + if (this.levels != null) { + this.levels.get(key); + } + // if not specified the in config properties, look for an annotation on the method + if (level == null) { + LogLevel annotation = method.getAnnotation(LogLevel.class); + if (annotation != null && annotation.value() != null) { + try { + level = Level.parse(annotation.value()); + } catch (IllegalArgumentException e) { + // bad value, just use the default + level = defaultLevel; + } + } + } + if (level == null) { + level = defaultLevel; + } + levels.put(method.getName(), level); + } + + ResourceBundle bundle = locateBundle(monitorInterface, bundleName); + + InvocationHandler handler = new LoggingHandler(logger, levels, bundle, formatters, defaultFormatter); + return monitorInterface + .cast(Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class[]{monitorInterface}, handler)); + } + + private static ResourceBundle locateBundle(Class monitorInterface, String bundleName) { + Locale locale = Locale.getDefault(); + ClassLoader cl = monitorInterface.getClassLoader(); + String packageName = monitorInterface.getPackage().getName(); + while (true) { + try { + return ResourceBundle.getBundle(packageName + '.' + bundleName, locale, cl); + } catch (MissingResourceException e) { + //ok + } + int index = packageName.lastIndexOf('.'); + if (index == -1) { + break; + } + packageName = packageName.substring(0, index); + } + try { + return ResourceBundle.getBundle(bundleName, locale, cl); + } catch (Exception e) { + return null; + } + } + + public void register(ExceptionFormatter formatter) { + formatters.add(formatter); + } + + public void unregister(ExceptionFormatter formatter) { + formatters.remove(formatter); + } + + private static final class LoggingHandler implements InvocationHandler { + private final Logger logger; + private final Map methodLevels; + private final ResourceBundle bundle; + private List formatters; + private ExceptionFormatter defaultFormatter; + + public LoggingHandler(Logger logger, + Map methodLevels, + ResourceBundle bundle, + List formatters, + ExceptionFormatter defaultFormatter) { + this.logger = logger; + this.methodLevels = methodLevels; + this.bundle = bundle; + this.formatters = formatters; + this.defaultFormatter = defaultFormatter; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String sourceMethod = method.getName(); + Level level = methodLevels.get(sourceMethod); + if (level != null && logger.isLoggable(level)) { + // construct the key for the resource bundle + String className = logger.getName(); + String key = className + '#' + sourceMethod; + + LogRecord logRecord = new LogRecord(level, key); + logRecord.setLoggerName(className); + logRecord.setSourceClassName(className); + logRecord.setSourceMethodName(sourceMethod); + logRecord.setParameters(args); + if (args != null) { + for (Object o : args) { + if (o instanceof Throwable) { + Throwable e = (Throwable) o; + ExceptionFormatter formatter = null; + for (ExceptionFormatter candidate : formatters) { + if (candidate.canFormat(e.getClass())) { + formatter = candidate; + break; + } + } + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + if (formatter != null) { + formatter.write(pw, e); + } else { + defaultFormatter.write(pw, e); + } + format(pw, e); + pw.close(); + logRecord.setMessage(writer.toString()); + break; + } + } + } + logRecord.setResourceBundle(bundle); + logger.log(logRecord); + } + return null; + } + + private void format(PrintWriter writer, Throwable throwable) { + writer.println(throwable.getClass().getName()); + StackTraceElement[] trace = throwable.getStackTrace(); + for (StackTraceElement aTrace : trace) { + writer.println("\tat " + aTrace); + } + Throwable ourCause = throwable.getCause(); + + if (ourCause != null) { + printStackTraceAsCause(writer, ourCause, trace); + } + } + + private void printStackTraceAsCause(PrintWriter pw, + Throwable throwable, + StackTraceElement[] causedTrace) { + + // Compute number of frames in common between this and caused + StackTraceElement[] trace = throwable.getStackTrace(); + int m = trace.length - 1; + int n = causedTrace.length - 1; + while (m >= 0 && n >= 0 && trace[m].equals(causedTrace[n])) { + m--; + n--; + } + int framesInCommon = trace.length - 1 - m; + + pw.println("Caused by: " + throwable.getClass().getName()); + + ExceptionFormatter formatter = null; + for (ExceptionFormatter candidate : formatters) { + if (candidate.canFormat(throwable.getClass())) { + formatter = candidate; + break; + } + } + if (formatter != null) { + formatter.write(pw, throwable); + } else { + defaultFormatter.write(pw, throwable); + } + + + for (int i = 0; i <= m; i++) { + pw.println("\tat " + trace[i]); + } + if (framesInCommon != 0) { + pw.println("\t... " + framesInCommon + " more"); + } + + // Recurse if we have a cause + Throwable ourCause = throwable.getCause(); + if (ourCause != null) { + printStackTraceAsCause(pw, ourCause, trace); + } + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java new file mode 100644 index 0000000000..92224d469f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import org.apache.tuscany.host.MonitorFactory; + +import java.util.Map; + +/** + * Helper for creating MonitorFactory instances. + * + * @version $$Rev$$ $$Date$$ + */ + +public final class MonitorFactoryUtil { + /** + * Hide the constructor + */ + private MonitorFactoryUtil() { + } + + /** + * Creates a MonitorFactory instance of the specified type. + * @param name fully qualified classname of the desired MonitorFactory type + * @param props collection of initialization properties + * @return a configured MonitorFactory instance, or null if the factory could not be instantiated. + */ + @SuppressWarnings("unchecked") + public static MonitorFactory createMonitorFactory(String name, Map props) { + Class clazz; + try { + clazz = (Class) Class.forName(name); + } catch (ClassNotFoundException cnfe) { + return null; + } catch (ClassCastException cce) { + return null; + } + + return createMonitorFactory(clazz, props); + } + + /** + * Creates a MonitorFactory instance of the specified type. + * @param mfc class of the desired MonitorFactory type + * @param props collection of initialization properties + * @return a configured MonitorFactory instance, or null if the factory could not be instantiated. + */ + public static MonitorFactory createMonitorFactory(Class mfc, Map props) { + MonitorFactory mf; + try { + mf = mfc.newInstance(); + mf.initialize(props); + } catch (InstantiationException e) { + throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + // allow IllegalArgumentException to propogate out + + return mf; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java new file mode 100644 index 0000000000..8ba3053c2f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.host.MonitorFactory; + +/** + * Implementation of a {@link MonitorFactory} that produces implementations that simply return. + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class NullMonitorFactory implements MonitorFactory { + /** + * Singleton wire hander that does nothing. + */ + private static final InvocationHandler NULL_MONITOR = new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) { + return null; + } + }; + + public void initialize(Map configProperties) { + } + + public T getMonitor(Class monitorInterface) { + /* + * This uses a reflection proxy to implement the monitor interface which + * is a simple but perhaps not very performant solution. Performance + * might be improved by code generating an implementation with empty methods. + */ + return monitorInterface.cast( + Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class[]{monitorInterface}, NULL_MONITOR)); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java new file mode 100644 index 0000000000..5ea24e4c9b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/IntentRegistryImpl.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.policy; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.model.Intent; +import org.apache.tuscany.spi.model.IntentName; +import org.apache.tuscany.spi.policy.IntentRegistry; + +/** + * The default implementation of a data intent registry + */ +public class IntentRegistryImpl implements IntentRegistry { + private final Map intentRepo = new HashMap(); + + public Collection getQualifiedIntents(final IntentName qualifiable, final QName artifact) { + List result = new ArrayList(); + for (IntentName intentName : intentRepo.keySet()) { + if (intentRepo.get(intentName).getAppliedArtifacts().contains(artifact) + && PolicyHelper.isQualifiedIntentFor(intentName, qualifiable, true)) { + result.add(intentName); + } + } + return result; + } + + public Collection inlineProfileIntent(final Collection intentNameList, + final QName artifact) { + + return getConcretIntentsInternal(intentNameList, artifact); + } + + private Collection getConcretIntentsInternal(final Collection intentNameList, + QName artifact) { + List result = new ArrayList(); + for (IntentName intentName : intentNameList) { + IntentEntry intentEntry = intentRepo.get(intentName); + if (!intentEntry.isProfileIntent()) { + if (intentEntry.getAppliedArtifacts().contains(artifact)) { + result.add(intentEntry.getName()); + } + } else { + result.addAll(getConcretIntentsInternal(intentEntry.getRequriedIntents(), artifact)); + } + } + return result; + } + + public boolean isApplicable(IntentName intentName, QName artifact) { + if (intentRepo.containsKey(intentName)) { + return intentRepo.get(intentName).getAppliedArtifacts().contains(artifact); + } + return false; + } + + public void register(Intent intent) { + + IntentEntry entry = new IntentEntry(intent); + // if the qualified intents have been registered, make the intent qualifiable(unqualified) + if (!getQualifiedIntents(intent.getName()).isEmpty()) { + entry.setQualified(false); + } + intentRepo.put(intent.getName(), entry); + List qualifiables = getAllQualifiableIntent(intent.getName()); + // set qualifiable intent of this intent unqualified + for (IntentName qualifiable : qualifiables) { + IntentEntry qualifiableEntry = intentRepo.get(qualifiable); + qualifiableEntry.setQualified(false); + for (QName artifact : intent.getAppliedArtifacts()) { + qualifiableEntry.addAppliedArtifacts(artifact); + } + } + } + + public void unRegister(Intent intent) { + if (intentRepo.containsKey(intent.getName())) { + IntentEntry intentEntry = intentRepo.get(intent.getName()); + List appliedArtifacts = intent.getAppliedArtifacts(); + for (QName artifact : appliedArtifacts) { + if (intentEntry.getAppliedArtifacts().contains(artifact)) { + intentEntry.removeappliedArtifact(artifact); + } + } + if (intentEntry.getAppliedArtifacts().isEmpty()) { + intentRepo.remove(intent.getName()); + } + } + } + + public boolean isQualifiedIntent(IntentName name) { + IntentEntry intentEntry = intentRepo.get(name); + return intentEntry.isQualified(); + } + + private List getQualifiedIntents(final IntentName qualifiable) { + List result = new ArrayList(); + for (IntentName intentName : intentRepo.keySet()) { + if (PolicyHelper.isQualifiedIntentFor(intentName, qualifiable, true)) { + result.add(intentName); + } + } + return result; + } + + private List getAllQualifiableIntent(final IntentName qualified) { + + List result = new ArrayList(); + for (IntentName intentName : intentRepo.keySet()) { + if (PolicyHelper.isQualifiedIntentFor(qualified, intentName, false)) { + result.add(intentName); + } + } + return result; + } + + /** + * Wrapper class for intent used internally + */ + private static final class IntentEntry extends Intent { + + /** + * Whether this intent is qualified, defaults to true + */ + private boolean isQualified = true; + + private IntentEntry(Intent intent) { + super(intent.getName(), intent.getDescription()); + appliedArtifacts.addAll(intent.getAppliedArtifacts()); + requriedIntents.addAll(intent.getRequriedIntents()); + } + + public boolean isQualified() { + return isQualified; + } + + public void setQualified(boolean isQualified) { + this.isQualified = isQualified; + } + + public void removeappliedArtifact(QName artifact) { + appliedArtifacts.remove(artifact); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java new file mode 100644 index 0000000000..94703f6abf --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.policy; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.policy.PolicyBuilderRegistry; +import org.apache.tuscany.spi.policy.SourcePolicyBuilder; +import org.apache.tuscany.spi.policy.TargetPolicyBuilder; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * The default policy builder + * + * @version $Rev$ $Date$ + */ +public class PolicyBuilderRegistryImpl implements PolicyBuilderRegistry { + + private final List> sourceBuilders; + private final List> targetBuilders; + + public PolicyBuilderRegistryImpl() { + sourceBuilders = new ArrayList>(); + targetBuilders = new ArrayList>(); + for (int i = 0; i <= FINAL; i++) { + sourceBuilders.add(new ArrayList()); + targetBuilders.add(new ArrayList()); + } + } + + public void registerTargetBuilder(int phase, TargetPolicyBuilder builder) { + assert INITIAL <= phase && phase <= FINAL : "Illegal phase"; + targetBuilders.get(phase).add(builder); + } + + public void registerSourceBuilder(int phase, SourcePolicyBuilder builder) { + assert INITIAL <= phase && phase <= FINAL : "Illegal phase"; + sourceBuilders.get(phase).add(builder); + } + + + public void buildSource(AbstractReferenceDefinition referenceDefinition, OutboundWire wire) throws BuilderException { + for (List builders : sourceBuilders) { + for (SourcePolicyBuilder builder : builders) { + builder.build(referenceDefinition, wire); + } + } + } + + public void buildTarget(ServiceDefinition serviceDefinition, InboundWire wire) throws BuilderException { + for (List builders : targetBuilders) { + for (TargetPolicyBuilder builder : builders) { + builder.build(serviceDefinition, wire); + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java new file mode 100644 index 0000000000..308e43c038 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyEngineImpl.java @@ -0,0 +1,297 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.policy; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.model.IntentMap; +import org.apache.tuscany.spi.model.IntentName; +import org.apache.tuscany.spi.model.PolicyContentModel; +import org.apache.tuscany.spi.model.PolicyModel; +import org.apache.tuscany.spi.model.PolicySet; +import org.apache.tuscany.spi.model.PolicySetReference; +import org.apache.tuscany.spi.model.Qualifier; +import org.apache.tuscany.spi.policy.IntentRegistry; +import org.apache.tuscany.spi.policy.PolicyEngine; +import org.apache.tuscany.spi.policy.PolicySetContainer; +import org.apache.tuscany.spi.policy.SCATypeManager; + +/** + * Default implementation of a polciy engine + */ +public class PolicyEngineImpl implements PolicyEngine { + private final IntentRegistry intentRegistry; + private final PolicySetContainer policySetContainer; + private final SCATypeManager scaTypeManager; + + public PolicyEngineImpl(IntentRegistry intentRegistry, + PolicySetContainer policySetContainer, + SCATypeManager scaTypeManager) { + this.intentRegistry = intentRegistry; + this.policySetContainer = policySetContainer; + this.scaTypeManager = scaTypeManager; + } + + @SuppressWarnings("unchecked") + public Collection getPolicy(final IntentName[] requires, + final QName[] policySetNames, + final QName artifactType) { + if (requires == null || requires.length == 0) { + return Collections.EMPTY_LIST; + } + Collection result = new ArrayList(); + Collection requiredIntents = java.util.Arrays.asList(requires); + Collection matchings; + + //handle profile intents + requiredIntents = intentRegistry.inlineProfileIntent(requiredIntents, artifactType); + // + if (policySetNames != null && policySetNames.length != 0) { + Collection explicitPolicySet = getExplicitPolicySet(policySetNames); + matchings = calculateExplicitPolicySet(requiredIntents, explicitPolicySet, artifactType, result); + //remove satisfied intent + requiredIntents.removeAll(matchings); + } + // + if (requiredIntents.size() > 0) { + matchings = findingAdditionalMatching(requiredIntents, artifactType, result); + requiredIntents.removeAll(matchings); + } + //If no collection of policySets covers all required intents, the configuration is not valid. + if (requiredIntents.size() > 0) { + //TODO + } + return result; + } + + + private boolean introspectPolicySet(PolicySet policySet, IntentName intent, QName artifactType, + Collection matchings) { + Collection appliedArtifacts = policySet.getAppliedArtifacts(); + boolean provide = false; + for (QName name : appliedArtifacts) { + if (this.scaTypeManager.isTypeOf(artifactType, name)) { + provide = true; + break; + } + } + if (!provide) { + return false; + } + //1. The required intent matches a provides intent in a policySet exactly. + if (policySet.getProvideIntents().contains(intent)) { + if (intentRegistry.isQualifiedIntent(intent)) { + addMatching(matchings, policySet); + } else { + Collection intentMaps = policySet.getIntentMaps(); + provide = searchIntentMaps(intent, intent, matchings, intentMaps); + if (provide) { + return true; + } + } + } else if (provideAbstract(intent, policySet.getProvideIntents())) { + // 2. The provides intent is a parent (e.g. prefix) of the required intent (in this case the policySet must + // have an intentMap entry for the requested qualifier) + Collection intentMaps = policySet.getIntentMaps(); + IntentName satisfiedIntent = getSatisfiedIntent(intent, policySet.getProvideIntents()); + provide = searchIntentMaps(intent, satisfiedIntent, matchings, intentMaps); + if (provide) { + return true; + } + } else if (provideQualifier(intent, policySet.getProvideIntents())) { + //3. The provides intent is more qualified than the required intent + if (intentRegistry.isQualifiedIntent(intent)) { + addMatching(matchings, policySet); + } else { + //TODO + } + } + + //handle PolicySetReference + Collection policySetReferences = policySet.getPolicySetReferences(); + for (PolicySetReference reference : policySetReferences) { + PolicySet referencedPolicySet = policySetContainer.getPolicySet(reference.getReference()); + if (introspectPolicySet(referencedPolicySet, intent, artifactType, matchings)) { + return true; + } + } + + return false; + } + + private void addMatching(Collection matching, PolicyContentModel policy) { + if (!policy.getWsPolicyAttachments().isEmpty()) { + matching.addAll(policy.getWsPolicyAttachments()); + } + if (!policy.getPolicyExtensions().isEmpty()) { + matching.addAll(policy.getPolicyExtensions()); + } + } + + private boolean searchIntentMaps(IntentName require, + IntentName satisfiedIntent, + Collection matchings, + Collection intentMaps) { + String qualifierName = getQualifierName(require, satisfiedIntent, intentMaps); + for (IntentMap intentMap : intentMaps) { + if (intentMap.getProvideIntents().contains(qualifierName)) { + Collection qualifiers = intentMap.getQualifiers(); + for (Qualifier qualifier : qualifiers) { + String nextQualifier = getNextQualifier(require, satisfiedIntent, intentMap); + if (qualifier.getName().equals(nextQualifier)) { + if (intentRegistry + .isQualifiedIntent(new IntentName(satisfiedIntent.toString() + "/" + nextQualifier))) { + addMatching(matchings, qualifier); + return true; + } else { + require = new IntentName(require.toString() + "/" + intentMap.getDefaultProvideIntent()); + satisfiedIntent = new IntentName(satisfiedIntent.toString() + "/" + qualifierName); + intentMaps = new ArrayList(0); + intentMaps.add(qualifier.getIntentMap()); + searchIntentMaps(require, satisfiedIntent, matchings, intentMaps); + } + break; + } + } + } + } + return false; + } + + private String getQualifierName(IntentName require, IntentName satisfiedIntent, Collection intentMaps) { + String[] requrieQualifiers = require.getQualifiedNames(); + String[] satisfiedQualifiers = satisfiedIntent.getQualifiedNames(); + if (requrieQualifiers.length == satisfiedQualifiers.length) { + return requrieQualifiers[requrieQualifiers.length - 1]; + } else if (requrieQualifiers.length > satisfiedQualifiers.length) { + return satisfiedQualifiers[satisfiedQualifiers.length - 1]; + } + //TODO raise exception + return null; + } + + private String getNextQualifier(IntentName require, IntentName satisfiedIntent, IntentMap intentMap) { + String[] requrieQualifiers = require.getQualifiedNames(); + String[] satisfiedQualifiers = satisfiedIntent.getQualifiedNames(); + if (requrieQualifiers.length > satisfiedQualifiers.length) { + return requrieQualifiers[satisfiedQualifiers.length]; + } else { + return intentMap.getDefaultProvideIntent(); + } + } + + private IntentName getSatisfiedIntent(IntentName require, Collection provides) { + for (IntentName name : provides) { + if (PolicyHelper.isQualifiedIntentFor(require, name, true)) { + return name; + } + } + //TODO raise exception + return null; + } + + private boolean provideAbstract(IntentName require, Collection provides) { + for (IntentName name : provides) { + if (PolicyHelper.isQualifiedIntentFor(require, name, true)) { + return true; + } + } + return false; + } + + private boolean provideQualifier(IntentName require, Collection provides) { + for (IntentName name : provides) { + if (PolicyHelper.isQualifiedIntentFor(name, require, true)) { + return true; + } + } + return false; + } + + private Collection getExplicitPolicySet(QName[] policySetNames) { + Collection result = new ArrayList(); + for (QName policySetName : policySetNames) { + PolicySet set = policySetContainer.getPolicySet(policySetName); + if (set != null) { + result.add(set); + } + } + return result; + } + + /** + * Step C. Calculate the list of explicitly specified policySets that apply to the target element as follows: 1. + * Start with the list of policySets specified in the element's policySet attribute. 2. If any of these explicitly + * listed policySets has an XPath expression in its appliesTo attribute that does not match the target element + * (binding or implementation) then the composite is invalid. It does not match if the XPath returns a result set + * that corresponds to XPath false. For example, a policySet could have appliesTo=”binding.ws/soaphttp”. This would + * return false if the target element is a element. 3. Include the values of policySet attributes + * from ancestor elements. 4. Remove any policySet where the XPath expression in that policySet’s appliesTo + * attribute does not match the target element. + *

      + * + * @param requires + * @param policies + * @return intent names was satisfied by this step. + */ + private Collection calculateExplicitPolicySet(Collection requires, + Collection policies, + QName artifactType, + Collection matchings) { + Collection satisfied = new ArrayList(); + for (IntentName intent : requires) { + for (PolicySet policySet : policies) { + if (introspectPolicySet(policySet, intent, artifactType, matchings)) { + satisfied.add(intent); + } + } + } + return satisfied; + } + + /** + * * The remaining required intents, if any, are provided by finding additional matching policySets within the SCA + * system. E. Choose the smallest collection of these policySets that match all remaining required intents. A + * policySet matches a required intent if any of the following are true: 1. The required intent matches a provides + * intent in a policySet exactly. 2. The provides intent is a parent (e.g. prefix) of the required intent (in this + * case the policySet must have an intentMap entry for the requested qualifier) 3. The provides intent is more + * qualified than the required intent All intents should now be satisfied. + * + * @param remainings + * @param artifactType + * @param matchings + */ + private Collection findingAdditionalMatching(final Collection remainings, + QName artifactType, + Collection matchings) { + Collection satisfied = new ArrayList(); + Collection policies = this.policySetContainer.getAllPolicySet(); + for (IntentName intent : remainings) { + for (PolicySet policySet : policies) { + if (introspectPolicySet(policySet, intent, artifactType, matchings)) { + satisfied.add(intent); + } + } + } + return satisfied; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java new file mode 100644 index 0000000000..50c94aaf13 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyHelper.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.policy; + +import org.apache.tuscany.spi.model.IntentName; + +/** + * Contains utility methods for dealing with policies + */ +public final class PolicyHelper { + + private PolicyHelper() { + } + + /** + * Whether qualified is qualified intent for qualifiable + *

      + * For example: sec.confidentiality/message is direct qualifier for sec.confidentiality. + * sec.confidentiality/message/body is qualifier for sec.confidentiality, but not a direct qualifier + * + * @param qualified qualified intent name + * @param qualifiable qualifiable intent name + * @param direct indicate whether to expect qualified is direct qualified intent for + * qualifiable + * @return whether qualified is qualified intent for qualifiable + */ + public static boolean isQualifiedIntentFor(final IntentName qualified, + final IntentName qualifiable, + boolean direct) { + if (qualified.equals(qualifiable) || !qualified.getDomain().equals(qualifiable.getDomain())) { + return false; + } + boolean result = true; + String[] shortArray = qualifiable.getQualifiedNames(); + String[] longArray = qualified.getQualifiedNames(); + if (longArray.length - shortArray.length < 1 && !direct) { + return false; + } else if (direct && longArray.length - shortArray.length != 1) { + return false; + } + for (int i = 0; i < shortArray.length; i++) { + if (!shortArray[i].equals(longArray[i])) { + result = false; + break; + } + } + return result; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java new file mode 100644 index 0000000000..36054dc2f6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.tuscany.core.databinding.xml.InputStream2Node; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * The property factory backed by the DataBindingframework + */ +public final class PropertyHelper { + + private static final XPathFactory FACTORY = XPathFactory.newInstance(); + + private PropertyHelper() { + } + + public static Document evaluate(NamespaceContext nsContext, Node node, String xPathExpression) + throws XPathExpressionException, ParserConfigurationException { + XPath path = FACTORY.newXPath(); + if (nsContext != null) { + path.setNamespaceContext(nsContext); + } else { + path.setNamespaceContext(new DOMNamespeceContext(node)); + } + XPathExpression expression = path.compile(xPathExpression); + Node result = (Node)expression.evaluate(node, XPathConstants.NODE); + if (result == null) { + return null; + } + + // TODO: How to wrap the result into a Document? + Document document = DOMHelper.newDocument(); + if (result instanceof Document) { + return (Document)result; + } else { + document.appendChild(document.importNode(result, true)); + return document; + } + } + + public static Document loadFromFile(String file, DeploymentContext deploymentContext) + throws LoaderException { + try { + URI uri = URI.create(file); + URL url = null; + if (!uri.isAbsolute()) { + url = deploymentContext.getClassLoader().getResource(file); + } else { + url = uri.toURL(); + } + InputStream is = url.openStream(); + try { + InputStream2Node transformer = new InputStream2Node(); + return (Document)transformer.transform(is, null); + } finally { + is.close(); + } + } catch (Exception e) { + throw new LoaderException(e); + } + } + + @SuppressWarnings("unchecked") + public static void processProperties(CompositeComponentType> parent, + ComponentDefinition> componentDefinition, + DeploymentContext deploymentContext) throws LoaderException { + Map> propertyValues = componentDefinition.getPropertyValues(); + + for (PropertyValue propValue : propertyValues.values()) { + String source = propValue.getSource(); + String file = propValue.getFile(); + if (source != null) { + try { + // $/... + int index = source.indexOf('/'); + if (index == -1) { + // Tolerating $prop + source = source + "/"; + index = source.length() - 1; + } + if (source.charAt(0) == '$') { + String name = source.substring(1, index); + Property compositeProp = parent.getProperties().get(name); + if (compositeProp == null) { + InvalidValueException ex = + new InvalidValueException( + "The 'source' cannot be resolved to a composite property"); + ex.addContextName(source); + throw ex; + } + + boolean prependValue = false; + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document compositePropDefValues = builder.newDocument(); + Node element = null; + for (int count = 0 ; count < compositeProp.getDefaultValues().size() ; ++count) { + element = compositeProp.getDefaultValues().get(count); + prependValue = element.getNodeName().equals("value"); + element = compositePropDefValues.adoptNode(element); + compositePropDefValues.appendChild(element); + } + // Adding /value because the document root is "value" + String path = source.substring(index); + String xpath = null; + Property componentProperty = (Property) + componentDefinition.getImplementation().getComponentType().getProperties().get(propValue.getName()); + if (prependValue) { + if ("/".equals(path)) { + // trailing / is not legal for xpath + xpath = "/value"; + } else { + xpath = "/value" + path; + } + } else { + xpath = path; + } + + // FIXME: How to deal with namespaces? + Document node = evaluate(null, compositePropDefValues, xpath); + //Document node = evaluate(null, compositeProp.getDefaultValues().get(0).getOwnerDocument(), xpath); + if (node != null) { + List values = new ArrayList(); + values.add(node); + propValue.setValue(values); + } + } else { + InvalidValueException ex = + new InvalidValueException("The 'source' has an invalid value"); + ex.addContextName(source); + throw ex; + } + } catch (Exception e) { + throw new LoaderException(e); + } + } else if (file != null) { + Property prop = + (Property)componentDefinition.getImplementation().getComponentType().getProperties() + .get(propValue.getName()); + Document document = loadFromFile(propValue.getFile(), deploymentContext); + List values = new ArrayList(); + if (prop.isMany()) { + //extract the property value elements from the loaded document + Element element = document.getDocumentElement(); + Node childNode = null; + for (int count = 0 ; count < element.getChildNodes().getLength() ; ++count) { + if (element.getChildNodes().item(count).getNodeType() == Document.ELEMENT_NODE) { + values.add((Element)element.getChildNodes().item(count)); + } + } + propValue.setValue(values); + propValue.setValueFactory(new SimpleMultivaluedPropertyObjectFactory(prop, propValue.getValue())); + } else { + values.add(document.getDocumentElement()); + propValue.setValue(values); + propValue.setValueFactory(new SimplePropertyObjectFactory(prop, (Element)propValue.getValue().get(0))); + } + } + } + } + + private static class DOMNamespeceContext implements NamespaceContext { + private Node node; + + /** + * @param node + */ + public DOMNamespeceContext(Node node) { + super(); + this.node = node; + } + + public String getNamespaceURI(String prefix) { + //return "http://foo"; + return node.lookupNamespaceURI(prefix); + } + + public String getPrefix(String namespaceURI) { + //return "foo"; + return node.lookupPrefix(namespaceURI); + } + + public Iterator getPrefixes(String namespaceURI) { + return null; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java new file mode 100644 index 0000000000..53b4f58b71 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.core.databinding.xml.DOMDataBinding; +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.osoa.sca.annotations.Constructor; +import org.osoa.sca.annotations.Scope; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +@Service(PropertyObjectFactory.class) +@Scope("COMPOSITE") +public class PropertyObjectFactoryImpl implements PropertyObjectFactory { + private DataBindingRegistry registry; + private Mediator mediator; + + public PropertyObjectFactoryImpl() { + } + + @Constructor( {"registry", "mediator"}) + public PropertyObjectFactoryImpl(@Autowire + DataBindingRegistry registry, @Autowire + Mediator mediator) { + super(); + this.registry = registry; + this.mediator = mediator; + } + + public ObjectFactory createObjectFactory(Property property, PropertyValue value) { + if (mediator == null) { + return new SimplePropertyObjectFactory(property, value.getValue().get(0)); + } + return new ObjectFactoryImpl(property, value); + } + + public ObjectFactory> createListObjectFactory(Property property, PropertyValue value) + throws LoaderException { + if (mediator == null) { + return new SimpleMultivaluedPropertyObjectFactory(property, value.getValue()); + } + return new ListObjectFactoryImpl(property, value); + } + + public class ObjectFactoryImplBase

      { + protected Property

      property; + protected PropertyValue

      propertyValue; + protected DataType sourceDataType; + protected DataType targetDataType; + + public ObjectFactoryImplBase(Property

      property, PropertyValue

      propertyValue) { + this.property = property; + this.propertyValue = propertyValue; + sourceDataType = + new DataType(DOMDataBinding.NAME, Node.class, new XMLType(null, this.property.getXmlType())); + TypeInfo typeInfo = null; + if (this.property.getXmlType() != null) { + if (SimpleTypeMapperExtension.isSimpleXSDType(this.property.getXmlType())) { + typeInfo = new TypeInfo(property.getXmlType(), true, null); + } else { + typeInfo = new TypeInfo(property.getXmlType(), false, null); + } + } else { + typeInfo = new TypeInfo(property.getXmlType(), false, null); + } + + XMLType xmlType = new XMLType(typeInfo); + /* + * ElementInfo elementInfo = new ElementInfo(null, typeInfo); + * sourceDataType.setMetadata(ElementInfo.class.getName(), + * elementInfo); + */ + Class javaType = this.property.getJavaType(); + String dataBinding = (String)property.getExtensions().get(DataBinding.class.getName()); + if (dataBinding != null) { + targetDataType = new DataType(dataBinding, javaType, xmlType); + } else { + targetDataType = new DataType(dataBinding, javaType, xmlType); + registry.introspectType(targetDataType, null); + } + } + } + + public class ObjectFactoryImpl

      extends ObjectFactoryImplBase

      implements ObjectFactory

      { + + public ObjectFactoryImpl(Property

      property, PropertyValue

      propertyValue) { + super(property, propertyValue); + } + + @SuppressWarnings("unchecked") + public P getInstance() throws ObjectCreationException { + return (P)mediator.mediate(propertyValue.getValue().get(0), sourceDataType, targetDataType, null); + } + } + + public class ListObjectFactoryImpl

      extends ObjectFactoryImplBase

      implements ObjectFactory> { + + public ListObjectFactoryImpl(Property

      property, PropertyValue

      propertyValue) { + super(property, propertyValue); + } + + @SuppressWarnings("unchecked") + public List

      getInstance() throws ObjectCreationException { + List

      instances = new ArrayList

      (); + for (int count = 0; count < propertyValue.getValue().size(); ++count) { + instances.add((P)mediator.mediate(propertyValue.getValue().get(count), + sourceDataType, + targetDataType, + null)); + } + return instances; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimpleMultivaluedPropertyObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimpleMultivaluedPropertyObjectFactory.java new file mode 100644 index 0000000000..85e41381a2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimpleMultivaluedPropertyObjectFactory.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.model.Property; +import org.w3c.dom.Element; + +public class SimpleMultivaluedPropertyObjectFactory

      implements ObjectFactory> { + private SimpleTypeMapperExtension typeMapper; + private Property

      property; + private List values; + private List

      instance; + + public SimpleMultivaluedPropertyObjectFactory(Property

      property, List value) { + super(); + + this.property = property; + this.values = (value == null) ? property.getDefaultValues() : value; + this.typeMapper = new SimpleTypeMapperExtension(); + } + + @SuppressWarnings("unchecked") + public List

      getInstance() throws ObjectCreationException { + if (values == null) { + return null; + } + + TypeInfo xmlType = null; + String text = null; + + if (instance == null) { + instance = new ArrayList

      (); + for (int count = 0 ; count < values.size() ; ++count) { + text = values.get(count).getTextContent(); + + if (property.getJavaType() == null) { + xmlType = new TypeInfo(property.getXmlType(), true, null); + } else { + xmlType = typeMapper.getXMLType(property.getJavaType()); + } + if (xmlType == null) { + throw new IllegalArgumentException("Complex property is not supported."); + } + instance.add((P)typeMapper.toJavaObject(xmlType.getQName(), text, null)); + } + } + return instance; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java new file mode 100644 index 0000000000..87d8d414e2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.model.Property; +import org.w3c.dom.Element; + +public class SimplePropertyObjectFactory

      implements ObjectFactory

      { + private SimpleTypeMapperExtension typeMapper; + private Property

      property; + private Element value; + private P instance; + + public SimplePropertyObjectFactory(Property

      property, Element value) { + super(); + + this.property = property; + this.value = (value == null) ? property.getDefaultValues().get(0) : value; + this.typeMapper = new SimpleTypeMapperExtension(); + } + + @SuppressWarnings("unchecked") + public P getInstance() throws ObjectCreationException { + if (value == null) { + return null; + } + if (instance == null) { + String text = value.getTextContent(); + TypeInfo xmlType = null; + if (property.getJavaType() == null) { + xmlType = new TypeInfo(property.getXmlType(), true, null); + } else { + xmlType = typeMapper.getXMLType(property.getJavaType()); + } + if (xmlType == null) { + throw new IllegalArgumentException("Complex property is not supported."); + } + instance = (P)typeMapper.toJavaObject(xmlType.getQName(), text, null); + } + return instance; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java new file mode 100644 index 0000000000..4dd4e792a2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.runtime; + +import java.net.URL; +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.core.bootstrap.Bootstrapper; +import org.apache.tuscany.core.bootstrap.DefaultBootstrapper; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.core.monitor.NullMonitorFactory; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.host.RuntimeInfo; +import org.apache.tuscany.host.management.ManagementService; +import org.apache.tuscany.host.runtime.InitializationException; +import org.apache.tuscany.host.runtime.TuscanyRuntime; +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ComponentException; +import org.apache.tuscany.spi.component.ComponentRegistrationException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.services.management.TuscanyManagementService; +import org.apache.tuscany.spi.wire.WireService; + +/** + * @version $Rev$ $Date$ + */ +public abstract class AbstractRuntime implements TuscanyRuntime { + private final XMLInputFactory xmlFactory; + private URL systemScdl; + private String applicationName; + private URL applicationScdl; + private ClassLoader hostClassLoader; + private ClassLoader applicationClassLoader; + private RuntimeInfo runtimeInfo; + private MonitorFactory monitorFactory; + private ManagementService managementService; + + private RuntimeComponent runtime; + private CompositeComponent systemComponent; + private CompositeComponent tuscanySystem; + private Deployer deployer; + private WireService wireService; + + protected AbstractRuntime() { + this(new NullMonitorFactory()); + } + + protected AbstractRuntime(MonitorFactory monitorFactory) { + this.monitorFactory = monitorFactory; + xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + } + + public URL getSystemScdl() { + return systemScdl; + } + + public void setSystemScdl(URL systemScdl) { + this.systemScdl = systemScdl; + } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public URL getApplicationScdl() { + return applicationScdl; + } + + public void setApplicationScdl(URL applicationScdl) { + this.applicationScdl = applicationScdl; + } + + public ClassLoader getApplicationClassLoader() { + return applicationClassLoader; + } + + public void setApplicationClassLoader(ClassLoader applicationClassLoader) { + this.applicationClassLoader = applicationClassLoader; + } + + public ClassLoader getHostClassLoader() { + return hostClassLoader; + } + + public void setHostClassLoader(ClassLoader hostClassLoader) { + this.hostClassLoader = hostClassLoader; + } + + public RuntimeInfo getRuntimeInfo() { + return runtimeInfo; + } + + public void setRuntimeInfo(RuntimeInfo runtimeInfo) { + this.runtimeInfo = runtimeInfo; + } + + public MonitorFactory getMonitorFactory() { + return monitorFactory; + } + + public void setMonitorFactory(MonitorFactory monitorFactory) { + this.monitorFactory = monitorFactory; + } + + public ManagementService getManagementService() { + return managementService; + } + + public void setManagementService(ManagementService managementService) { + this.managementService = managementService; + } + + protected XMLInputFactory getXMLFactory() { + return xmlFactory; + } + + protected RuntimeComponent getRuntime() { + return runtime; + } + + protected CompositeComponent getSystemComponent() { + return systemComponent; + } + + protected CompositeComponent getTuscanySystem() { + return tuscanySystem; + } + + protected Deployer getDeployer() { + return deployer; + } + + protected WireService getWireService() { + return wireService; + } + + public void initialize() throws InitializationException { + Bootstrapper bootstrapper = createBootstrapper(); + runtime = bootstrapper.createRuntime(); + runtime.start(); + + systemComponent = runtime.getSystemComponent(); + registerSystemComponents(); + systemComponent.start(); + + // deploy the system scdl + try { + tuscanySystem = + deploySystemScdl(bootstrapper.createDeployer(), + systemComponent, + ComponentNames.TUSCANY_SYSTEM, + getSystemScdl(), + getClass().getClassLoader()); + } catch (LoaderException e) { + throw new InitializationException(e); + } catch (BuilderException e) { + throw new InitializationException(e); + } catch (ComponentException e) { + throw new InitializationException(e); + } + tuscanySystem.start(); + + this.deployer = locateDeployer(); + this.wireService = locateWireService(); + } + + public void destroy() { + this.wireService = null; + this.deployer = null; + if (tuscanySystem != null) { + tuscanySystem.stop(); + tuscanySystem = null; + } + if (systemComponent != null) { + systemComponent.stop(); + systemComponent = null; + } + if (runtime != null) { + runtime.stop(); + runtime = null; + } + } + + protected Bootstrapper createBootstrapper() { + TuscanyManagementService tms = (TuscanyManagementService)getManagementService(); + return new DefaultBootstrapper(getMonitorFactory(), xmlFactory, tms); + } + + protected void registerSystemComponents() throws InitializationException { + try { + systemComponent.registerJavaObject(RuntimeInfo.COMPONENT_NAME, RuntimeInfo.class, runtimeInfo); + systemComponent.registerJavaObject("MonitorFactory", MonitorFactory.class, getMonitorFactory()); + } catch (ComponentRegistrationException e) { + throw new InitializationException(e); + } + } + + protected Deployer locateDeployer() throws InitializationException { + SCAObject deployerComponent = tuscanySystem.getSystemChild(ComponentNames.TUSCANY_DEPLOYER); + if (!(deployerComponent instanceof AtomicComponent)) { + throw new InitializationException("Deployer must be an atomic component"); + } + try { + return (Deployer)((AtomicComponent)deployerComponent).getTargetInstance(); + } catch (TargetResolutionException e) { + throw new InitializationException(e); + } + } + + protected WireService locateWireService() throws InitializationException { + SCAObject wireServiceComponent = tuscanySystem.getSystemChild(ComponentNames.TUSCANY_WIRE_SERVICE); + if (!(wireServiceComponent instanceof AtomicComponent)) { + throw new InitializationException("WireService must be an atomic component"); + } + try { + return (WireService)((AtomicComponent)wireServiceComponent).getTargetInstance(); + } catch (TargetResolutionException e) { + throw new InitializationException(e); + } + } + + protected CompositeComponent deploySystemScdl(Deployer deployer, + CompositeComponent parent, + String name, + URL systemScdl, + ClassLoader systemClassLoader) throws LoaderException, + BuilderException, ComponentException { + + SystemCompositeImplementation impl = new SystemCompositeImplementation(); + impl.setScdlLocation(systemScdl); + impl.setClassLoader(systemClassLoader); + ComponentDefinition definition = + new ComponentDefinition(name, impl); + + return (CompositeComponent)deployer.deploy(parent, definition); + } + + protected CompositeComponent deployApplicationScdl(Deployer deployer, + CompositeComponent parent, + String name, + URL applicationScdl, + ClassLoader applicationClassLoader) throws LoaderException, + BuilderException, ComponentException { + + CompositeImplementation impl = new CompositeImplementation(); + impl.setScdlLocation(applicationScdl); + impl.setClassLoader(applicationClassLoader); + ComponentDefinition definition = + new ComponentDefinition(name, impl); + + return (CompositeComponent)deployer.deploy(parent, definition); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntime.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntime.java new file mode 100644 index 0000000000..e192b18e5f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntime.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.runtime.mini; + +import org.apache.tuscany.host.runtime.TuscanyRuntime; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetResolutionException; + +/** + * @version $Rev$ $Date$ + */ +public interface SimpleRuntime extends TuscanyRuntime { + CompositeComponent start() throws Exception; + T getSystemService(Class type, String name) throws TargetResolutionException; +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeImpl.java new file mode 100644 index 0000000000..bb9a32e7e0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeImpl.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.runtime.mini; + +import static org.apache.tuscany.spi.bootstrap.ComponentNames.TUSCANY_ASSEMBLY_SERVICE; +import static org.apache.tuscany.spi.bootstrap.ComponentNames.TUSCANY_CONTRIBUTION_SERVICE; + +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.api.annotation.LogLevel; +import org.apache.tuscany.core.launcher.CompositeContextImpl; +import org.apache.tuscany.core.monitor.JavaLoggingMonitorFactory; +import org.apache.tuscany.core.runtime.AbstractRuntime; +import org.apache.tuscany.core.services.deployment.AssemblyServiceImpl; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.host.RuntimeInfo; +import org.apache.tuscany.host.deployment.AssemblyService; +import org.apache.tuscany.host.deployment.ContributionService; +import org.apache.tuscany.host.monitor.FormatterRegistry; +import org.apache.tuscany.host.runtime.InitializationException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ComponentRegistrationException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.osoa.sca.CompositeContext; +import org.osoa.sca.CurrentCompositeContext; + +/** + * @version $Rev$ $Date$ + */ +public class SimpleRuntimeImpl extends AbstractRuntime implements SimpleRuntime { + protected JavaLoggingMonitorFactory monitorFactory; + protected SimpleMonitor monitor; + protected CompositeComponent application; + + public SimpleRuntimeImpl(SimpleRuntimeInfo runtimeInfo) { + super(); + monitorFactory = new JavaLoggingMonitorFactory(); + setMonitorFactory(monitorFactory); + monitor = monitorFactory.getMonitor(SimpleMonitor.class); + ClassLoader hostClassLoader = ClassLoader.getSystemClassLoader(); + setHostClassLoader(hostClassLoader); + setSystemScdl(runtimeInfo.getSystemSCDL()); + setRuntimeInfo(runtimeInfo); + } + + public interface SimpleMonitor { + @LogLevel("SEVERE") + void runError(Exception e); + } + + public CompositeComponent start() throws Exception { + initialize(); + ContributionService contributionService = + getSystemService(ContributionService.class, TUSCANY_CONTRIBUTION_SERVICE); + CompositeComponent composite = getTuscanySystem(); + // TODO: Make assembly service a pluggable component? + AssemblyService assemblyService = new AssemblyServiceImpl(contributionService, composite); + composite.registerJavaObject(TUSCANY_ASSEMBLY_SERVICE, AssemblyService.class, assemblyService); + + SimpleRuntimeInfo runtimeInfo = (SimpleRuntimeInfo)getRuntimeInfo(); + int i = 0; + for (URL ext : runtimeInfo.getExtensionSCDLs()) { + CompositeComponent extensionComponent = + deploySystemScdl(getDeployer(), getTuscanySystem(), "tuscany.extension." + (i++), ext, runtimeInfo + .getClassLoader()); + extensionComponent.start(); + } + + URI contributionId = runtimeInfo.getContributionURI(); + contributionService.contribute(contributionId, runtimeInfo.getContributionRoot(), false); + URI compositeDefinitionId = contributionId.resolve(runtimeInfo.getCompositePath()); + + application = + (CompositeComponent)assemblyService.addCompositeToDomain(contributionId, compositeDefinitionId, runtimeInfo + .getCompositePath()); + + CompositeContext context = new CompositeContextImpl(application, getWireService()); + CurrentCompositeContext.setContext(context); + return application; + } + + public T getSystemService(Class type, String name) throws TargetResolutionException { + SCAObject child = getTuscanySystem().getSystemChild(name); + if (child == null) { + return null; + } + AtomicComponent service = (AtomicComponent)child; + return type.cast(service.getTargetInstance()); + } + + @Override + protected void registerSystemComponents() throws InitializationException { + try { + // initialize the runtime info + CompositeComponent parent = getSystemComponent(); + parent.registerJavaObject("RuntimeInfo", RuntimeInfo.class, getRuntimeInfo()); + + // register the monitor factory + if (monitorFactory instanceof FormatterRegistry) { + List> interfazes = new ArrayList>(2); + interfazes.add(MonitorFactory.class); + interfazes.add(FormatterRegistry.class); + parent.registerJavaObject("MonitorFactory", interfazes, monitorFactory); + } else { + parent.registerJavaObject("MonitorFactory", MonitorFactory.class, monitorFactory); + } + } catch (ComponentRegistrationException e) { + throw new InitializationException(e); + } + } + + @Override + public void destroy() { + CurrentCompositeContext.setContext(null); + application.stop(); + super.destroy(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfo.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfo.java new file mode 100644 index 0000000000..10b88d9e47 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfo.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.runtime.mini; + +import java.net.URI; +import java.net.URL; +import java.util.List; + +import org.apache.tuscany.host.RuntimeInfo; + +/** + * @version $Rev$ $Date$ + */ +public interface SimpleRuntimeInfo extends RuntimeInfo { + String DEFAULT_SYSTEM_SCDL = "META-INF/tuscany/default-system.composite"; + String SYSTEM_SCDL = "system.composite"; + String EXTENSION_SCDL = "META-INF/sca/extension.composite"; + String SERVICE_SCDL = "META-INF/sca/service.composite"; + String META_APPLICATION_SCDL = "META-INF/sca/application.composite"; + String APPLICATION_SCDL = "application.composite"; + + ClassLoader getClassLoader(); + + String getCompositePath(); + + URL getSystemSCDL(); + List getExtensionSCDLs(); + URL getContributionRoot(); + URI getContributionURI(); + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfoImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfoImpl.java new file mode 100644 index 0000000000..a9e0f2a114 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/mini/SimpleRuntimeInfoImpl.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.runtime.mini; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +import org.apache.tuscany.core.util.FileHelper; +import org.apache.tuscany.host.AbstractRuntimeInfo; + +/** + * @version $Rev$ $Date$ + */ +public class SimpleRuntimeInfoImpl extends AbstractRuntimeInfo implements SimpleRuntimeInfo { + private ClassLoader classLoader; + private String compositePath; + + private List extensions; + private URL applicationSCDL; + private URL systemSCDL; + + private URL contributionURL; + private URI contributionURI; + + /** + * @param classLoader + * @param compositePath + * @param extensions + * @param applicationSCDL + * @param systemSCDL + */ + public SimpleRuntimeInfoImpl(ClassLoader classLoader, + URL systemSCDL, + List extensions, + URI contributionURI, + URL applicationSCDL, + String compositePath) { + this(classLoader, compositePath); + this.extensions = extensions; + this.applicationSCDL = applicationSCDL; + this.systemSCDL = systemSCDL; + this.contributionURI = contributionURI; + } + + public SimpleRuntimeInfoImpl(ClassLoader classLoader, String compositePath) { + // super(domain, applicationRootDirectory, baseUrl, online, runtimeId); + super(URI.create("sca://domain/local"), null, null, false, "simple"); + if (classLoader != null) { + this.classLoader = classLoader; + } else { + classLoader = Thread.currentThread().getContextClassLoader(); + } + this.compositePath = compositePath != null ? compositePath : APPLICATION_SCDL; + getApplicationSCDL(); + this.contributionURI = URI.create("/default"); + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public String getCompositePath() { + return compositePath; + } + + public final URL getApplicationSCDL() { + if (applicationSCDL == null) { + applicationSCDL = classLoader.getResource(compositePath); + if (applicationSCDL == null) { + applicationSCDL = classLoader.getResource(APPLICATION_SCDL); + if (applicationSCDL == null) { + applicationSCDL = classLoader.getResource(META_APPLICATION_SCDL); + if (applicationSCDL != null) { + compositePath = META_APPLICATION_SCDL; + } + } else { + if (compositePath == null) { + compositePath = APPLICATION_SCDL; + } + } + if (applicationSCDL == null) { + throw new IllegalArgumentException("application SCDL not found: " + APPLICATION_SCDL); + } + } + } + return applicationSCDL; + } + + public URL getContributionRoot() { + if (contributionURL == null) { + contributionURL = getContributionLocation(getApplicationSCDL(), compositePath); + } + return contributionURL; + } + + public List getExtensionSCDLs() { + if (extensions == null) { + try { + List extensionURLs = new ArrayList(); + Enumeration urls = classLoader.getResources(SERVICE_SCDL); + extensionURLs.addAll(Collections.list(urls)); + urls = classLoader.getResources(EXTENSION_SCDL); + extensionURLs.addAll(Collections.list(urls)); + if (extensions != null) { + for (URL ext : extensions) { + if (!extensionURLs.contains(ext)) { + extensionURLs.add(ext); + } + } + } + extensions = extensionURLs; + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + return extensions; + } + + public URL getSystemSCDL() { + if (systemSCDL == null) { + systemSCDL = classLoader.getResource(SYSTEM_SCDL); + if (systemSCDL == null) { + systemSCDL = classLoader.getResource(DEFAULT_SYSTEM_SCDL); + } + } + return systemSCDL; + } + + private static URL getContributionLocation(URL applicationSCDL, String compositePath) { + URL root = null; + // "jar:file://....../something.jar!/a/b/c/app.composite" + try { + String scdlUrl = applicationSCDL.toExternalForm(); + String protocol = applicationSCDL.getProtocol(); + if ("file".equals(protocol)) { + // directory contribution + if (scdlUrl.endsWith(compositePath)) { + String location = scdlUrl.substring(0, scdlUrl.lastIndexOf(compositePath)); + // workaround from evil url/uri form maven + root = FileHelper.toFile(new URL(location)).toURI().toURL(); + } + + } else if ("jar".equals(protocol)) { + // jar contribution + String location = scdlUrl.substring(4, scdlUrl.lastIndexOf("!/")); + // workaround from evil url/uri form maven + root = FileHelper.toFile(new URL(location)).toURI().toURL(); + } + } catch (MalformedURLException mfe) { + throw new IllegalArgumentException(mfe); + } + + return root; + } + + public URI getContributionURI() { + return contributionURI; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java new file mode 100644 index 0000000000..f50e8544a3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.artifact; + +import java.io.File; +import java.net.MalformedURLException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * An implementation of ArtifactRepository that uses a local Maven2 repository. + * + * @version $Rev$ $Date$ + */ +public class LocalMavenRepository implements ArtifactRepository { + private File localRepo; + + /** + * Constructor specifying the location of the local repo. Relative paths are resolved against the user's home + * directory. + * + * @param repoPath the path to the local repo + */ + public LocalMavenRepository(@Property(name = "repository") String repoPath) { + String home = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty("user.home"); + } + }); + this.localRepo = new File(home, repoPath); + } + + public void resolve(Artifact artifact) { + if (artifact.getUrl() != null) { + return; + } + + String path = getPath(artifact); + File artifactFile = new File(localRepo, path); + if (artifactFile.exists()) { + try { + artifact.setUrl(artifactFile.toURI().toURL()); + } catch (MalformedURLException e) { + // toURI should have escaped the filename to allow it to be converted to a URL + throw new AssertionError(); + } + } + } + + /** + * Return the path into the repo for an artifact. The path for an artifact is ${group.replace('.', + * '/')}/$[name}/${version}/${name}-${version}[-${classifier}].${type} + * + * @param artifact the artifact to resolve + * @return the path into the repo for the artifact + */ + protected String getPath(Artifact artifact) { + StringBuilder builder = new StringBuilder(); + if (artifact.getGroup() != null) { + builder.append(artifact.getGroup().replace('.', '/')).append('/'); + } + builder.append(artifact.getName()).append('/'); + builder.append(artifact.getVersion()).append('/'); + + builder.append(artifact.getName()).append('-').append(artifact.getVersion()); + if (artifact.getClassifier() != null) { + builder.append('-').append(artifact.getClassifier()); + } + builder.append('.').append(artifact.getType()); + return builder.toString(); + } + + public void resolve(Collection artifacts) { + for (Artifact artifact : artifacts) { + resolve(artifact); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ArtifactResolverRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ArtifactResolverRegistryImpl.java new file mode 100644 index 0000000000..a8fd3ba737 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ArtifactResolverRegistryImpl.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment; + +import java.net.URI; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.deployer.ArtifactResolver; +import org.apache.tuscany.spi.deployer.ArtifactResolverRegistry; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.Contribution; +import org.osoa.sca.annotations.EagerInit; + +/** + * @version $Rev$ $Date$ + */ +@EagerInit +public class ArtifactResolverRegistryImpl implements ArtifactResolverRegistry { + private Map registry = new HashMap(); + + public void registerResolver(Class modelClass, ArtifactResolver resolver) { + registry.put(modelClass, resolver); + } + + public void unregisterResolver(Class modelClass) { + registry.remove(modelClass); + } + + public T resolve(Contribution contribution, + Class modelClass, + String namespace, + String name, + Map attributes, + DeploymentContext context) { + ArtifactResolver resolver = registry.get(modelClass); + if (resolver == null) { + return null; + } + return resolver.resolve(contribution, modelClass, namespace, name, attributes, context); + } + + public URL resolve(Contribution contribution, String targetNamespace, String location, String baseURI) { + // FIXME: What's a URI resolver? + ArtifactResolver resolver = registry.get(URI.class); + if (resolver == null) { + return null; + } + return resolver.resolve(contribution, targetNamespace, location, baseURI); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java new file mode 100644 index 0000000000..6982a9fa58 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/AssemblyServiceImpl.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.host.deployment.AssemblyService; +import org.apache.tuscany.host.deployment.ContributionService; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.host.deployment.UnsupportedContentTypeException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.ComponentException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.deployer.ChangeSetHandler; +import org.apache.tuscany.spi.deployer.ChangeSetHandlerRegistry; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.osoa.sca.annotations.Constructor; + +/** + * @version $Rev$ $Date$ + */ +public class AssemblyServiceImpl implements AssemblyService, ChangeSetHandlerRegistry { + private final Map registry = new HashMap(); + + private final ContributionService contributionService; + + private final CompositeComponent domain; + + @Constructor + public AssemblyServiceImpl(@Autowire ContributionService contributionService, CompositeComponent domain) { + this.contributionService = contributionService; + this.domain = domain; + } + + public Object addCompositeToDomain(URI contribution, URI composite, String artifactName) + throws DeploymentException { + + /*Contribution contributionMetadata = + (Contribution)this.contributionService.getContribution(contribution); + DeployedArtifact scdlArtifact = contributionMetadata.getArtifacts().get(composite); + + ComponentDefinition model = + (ComponentDefinition)scdlArtifact.getModelObject(CompositeComponentType.class, null);*/ + + ComponentDefinition model = + (ComponentDefinition) this.contributionService.resolve(contribution, ComponentDefinition.class, null, artifactName); + + Component component = null; + Deployer deployer = null; + + SCAObject child = this.domain.getSystemChild(ComponentNames.TUSCANY_DEPLOYER); + assert child instanceof AtomicComponent : "Deployer must be an atomic component"; + + try { + + deployer = (Deployer)((AtomicComponent)child).getTargetInstance(); + component = deployer.deployFromContribution(this.domain, model); + + } catch (TargetResolutionException e) { + throw new DomainUpdateException(e); + } catch (BuilderException e) { + throw new DomainUpdateException(e); + } catch (ComponentException e) { + throw new DomainUpdateException(e); + } + component.start(); + + return component; + } + + public void applyChanges(URL changeSet) throws DeploymentException, IOException { + if (changeSet == null) { + throw new IllegalArgumentException("changeSet is null"); + } + + URLConnection connection = changeSet.openConnection(); + String contentType = connection.getContentType(); + // todo try and figure out content type from the URL + if (contentType == null) { + throw new UnsupportedContentTypeException(null, changeSet.toString()); + } + + InputStream is = connection.getInputStream(); + try { + applyChanges(is, contentType); + } finally { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } + + public void applyChanges(InputStream changeSet, String contentType) throws DeploymentException, IOException { + if (changeSet == null) { + throw new IllegalArgumentException("changeSet is null"); + } + if (contentType == null) { + throw new IllegalArgumentException("contentType is null"); + } + + ChangeSetHandler handler = registry.get(contentType); + if (handler == null) { + throw new UnsupportedContentTypeException(contentType); + } + + handler.applyChanges(changeSet); + } + + public void register(ChangeSetHandler handler) { + registry.put(handler.getContentType(), handler); + } + + public T getDefinition(URI contribution, Class type, String namespace, String name) { + return contributionService.resolve(contribution, type, namespace, name); + } + + public Object getDomainComposite() { + return domain; + } + + public void removeCompositeFromDomain(URI contribution, URI composite) throws DeploymentException { + // TODO: + throw new UnsupportedOperationException("To be implemented"); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java new file mode 100644 index 0000000000..013d916c1d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContentTypeDescriberImpl.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.core.util.FileHelper; +import org.apache.tuscany.spi.deployer.ContentType; +import org.apache.tuscany.spi.deployer.ContentTypeDescriber; +import org.apache.tuscany.spi.model.Contribution; +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Service; + +/** + * Implementation of the content describer + * + * @version $Rev$ $Date$ + */ +@EagerInit +@Service(ContentTypeDescriber.class) +public class ContentTypeDescriberImpl implements ContentTypeDescriber { + private final Map contentTypeRegistry = new HashMap(); + + public ContentTypeDescriberImpl() { + super(); + init(); + } + + /** + * Initialize contentType registry with know types based on known file + * extensions + */ + private void init() { + contentTypeRegistry.put("COMPOSITE", ContentType.COMPOSITE); + contentTypeRegistry.put("SCDL", ContentType.COMPOSITE); + contentTypeRegistry.put("WSDL", ContentType.WSDL); + contentTypeRegistry.put("JAR", ContentType.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 url + * @param defaultContentType + * @return + */ + public String getContentType(URL resourceURL, String defaultContentType) { + URLConnection connection = null; + String contentType = defaultContentType; + + if (resourceURL.getProtocol().equals("file") && FileHelper.toFile(resourceURL).isDirectory()) { + // Special case : contribution is a folder + contentType = ContentType.FOLDER; + } else if (resourceURL.toExternalForm().endsWith(Contribution.SCA_CONTRIBUTION_META) + || resourceURL.toExternalForm().endsWith(Contribution.SCA_CONTRIBUTION_GENERATED_META)) { + // Special case : contribution metadata + contentType = ContentType.CONTRIBUTION_METADATA; + } else { + contentType = resolveContentyTypeByExtension(resourceURL); + if (contentType == null) { + try { + connection = resourceURL.openConnection(); + contentType = connection.getContentType(); + + if (contentType == null || contentType.equals("content/unknown")) { + // here we couldn't figure out from our registry or from URL 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/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java new file mode 100644 index 0000000000..f06010a0ab --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionDirectoryWatcher.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment; + +import java.io.File; +import java.io.IOException; + +import org.apache.tuscany.host.deployment.ContributionService; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Property; + +@EagerInit +public class ContributionDirectoryWatcher { + private final String path; + + private final ContributionService contributionService; + + public ContributionDirectoryWatcher(@Autowire + ContributionService contributionService, @Property(name = "path") + String path) { + this.path = path; + this.contributionService = contributionService; + } + + @Init + public void init() { + File extensionDir = new File(path); + if (!extensionDir.isDirectory()) { + // we don't have an extension directory, there's nothing to do + return; + } + + File[] files = extensionDir.listFiles(); + for (File file : files) { + try { + if (file.isDirectory()) { + this.contributionService.contribute(null, file.toURL(), false); + } else { + this.contributionService.contribute(null, file.toURL(), true); + } + } catch (DeploymentException de) { + // FIXME handle this + de.printStackTrace(); + } catch (IOException ioe) { + // FIXME handle this + ioe.printStackTrace(); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionLoader.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionLoader.java new file mode 100644 index 0000000000..eef4bd30af --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionLoader.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import static org.osoa.sca.Constants.SCA_NS; + +import java.net.URI; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.ContributionImport; +import org.apache.tuscany.spi.model.ModelObject; +import org.osoa.sca.annotations.Constructor; + +/** + * Loader that handles <include> elements. + * + * @version $Rev$ $Date$ + */ +public class ContributionLoader extends LoaderExtension { + private static final QName CONTRIBUTION = new QName(SCA_NS, "contribution"); + private static final QName DEPLOYABLE = new QName(SCA_NS, "deployable"); + private static final QName IMPORT = new QName(SCA_NS, "import"); + private static final QName EXPORT = new QName(SCA_NS, "export"); + + @Constructor({"registry"}) + public ContributionLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return CONTRIBUTION; + } + + public Contribution load(CompositeComponent parent, + ModelObject object, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + + Contribution contribution = new Contribution(); + while (true) { + int event = reader.next(); + switch (event) { + case START_ELEMENT: + QName element = reader.getName(); + if (DEPLOYABLE.equals(element)) { + String name = reader.getAttributeValue(null, "composite"); + if (name == null) { + throw new InvalidValueException("Attribute 'composite' is missing"); + } + QName compositeName = null; + int index = name.indexOf(':'); + if (index != -1) { + String prefix = name.substring(0, index); + String localPart = name.substring(index); + String ns = reader.getNamespaceContext().getNamespaceURI(prefix); + if (ns == null) { + throw new InvalidValueException("Invalid prefix: " + prefix); + } + compositeName = new QName(ns, localPart, prefix); + } else { + String prefix = ""; + String ns = reader.getNamespaceURI(); + String localPart = name; + compositeName = new QName(ns, localPart, prefix); + } + contribution.getDeployables().add(compositeName); + } else if (IMPORT.equals(element)) { + String ns = reader.getAttributeValue(null, "namespace"); + if (ns == null) { + throw new InvalidValueException("Attribute 'namespace' is missing"); + } + String location = reader.getAttributeValue(null, "location"); + ContributionImport contributionImport = new ContributionImport(); + if (location != null) { + contributionImport.setLocation(URI.create(location)); + } + contributionImport.setNamespace(ns); + contribution.getImports().add(contributionImport); + } else if (EXPORT.equals(element)) { + String ns = reader.getAttributeValue(null, "namespace"); + if (ns == null) { + throw new InvalidValueException("Attribute 'namespace' is missing"); + } + contribution.getExports().add(ns); + } + break; + case XMLStreamConstants.END_ELEMENT: + if (CONTRIBUTION.equals(reader.getName())) { + return contribution; + } + break; + + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java new file mode 100644 index 0000000000..47f457d396 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionProcessorRegistryImpl.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.host.deployment.UnsupportedContentTypeException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.ContentTypeDescriber; +import org.apache.tuscany.spi.deployer.ContributionProcessor; +import org.apache.tuscany.spi.deployer.ContributionProcessorRegistry; +import org.apache.tuscany.spi.model.Contribution; +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Service; + +/** + * Default implementation of ContributionProcessorRegistry + * + * @version $Rev$ $Date$ + */ +@EagerInit +@Service(ContributionProcessorRegistry.class) +public class ContributionProcessorRegistryImpl implements ContributionProcessorRegistry { + /** + * Processor registry + */ + private Map registry = new HashMap(); + /** + * Helper method to describe contentType for each artifact + */ + private ContentTypeDescriber contentTypeDescriber; + + public ContributionProcessorRegistryImpl(@Autowire ContentTypeDescriber contentTypeDescriber) { + if (contentTypeDescriber == null) { + this.contentTypeDescriber = new ContentTypeDescriberImpl(); + } else { + this.contentTypeDescriber = contentTypeDescriber; + } + } + + public void register(String contentType, ContributionProcessor processor) { + registry.put(contentType, processor); + } + + public void unregister(String contentType) { + registry.remove(contentType); + } + + public void processContent(Contribution contribution, URI source, InputStream inputStream) + throws DeploymentException, IOException { + + URL locationURL = contribution.getArtifact(source).getLocation(); + String contentType = this.contentTypeDescriber.getContentType(locationURL, null); + if (contentType == null) { + throw new UnsupportedContentTypeException("Invalid contentType: null"); + } + + ContributionProcessor processor = this.registry.get(contentType); + if (processor == null) { + throw new UnsupportedContentTypeException(contentType, locationURL.getPath()); + } + try { + processor.processContent(contribution, source, inputStream); + } catch ( Exception e ) { + e.printStackTrace(); + } + + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java new file mode 100644 index 0000000000..b56c7fe263 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionRepositoryImpl.java @@ -0,0 +1,275 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.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.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +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.core.util.FileHelper; +import org.apache.tuscany.core.util.IOHelper; +import org.apache.tuscany.spi.deployer.ContributionRepository; +import org.osoa.sca.annotations.Constructor; +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Property; + +/** + * The default implementation of ContributionRepository + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class ContributionRepositoryImpl implements ContributionRepository { + private static final String NS = "http://tuscany.apache.org/xmlns/1.0-SNAPSHOT"; + private final File rootFile; + private Map contributionMap = new HashMap(); + + private URI domain; + private XMLInputFactory factory; + + /** + * Constructor with repository root + * + * @param repository + */ + @Constructor + public ContributionRepositoryImpl(@Property(name = "repository") + final String repository) 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; + } + }); + } + this.rootFile = new File(root); + this.domain = rootFile.toURI(); + FileHelper.forceMkdir(rootFile); + if (!rootFile.exists() || !rootFile.isDirectory() || !rootFile.canRead()) { + throw new IOException("The root is not a directory: " + repository); + } + factory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + } + + 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(URI contribution) { + // FIXME: Map the contribution URI to a file? + return new File(rootFile, "contributions" + File.separator + contribution.getPath()); + } + + /** + * Write a specific source inputstream to a file on disk + * + * @param source contents of the file to be written to disk + * @param target file to be written + * @throws IOException + */ + public static void copy(InputStream source, File target) throws IOException { + BufferedOutputStream out = null; + BufferedInputStream in = null; + + try { + out = new BufferedOutputStream(new FileOutputStream(target)); + in = new BufferedInputStream(source); + IOHelper.copy(in, out); + } finally { + IOHelper.closeQuietly(out); + IOHelper.closeQuietly(in); + } + } + + public URL store(URI contribution, InputStream contributionStream) throws IOException { + // where the file should be stored in the repository + File location = mapToFile(contribution); + FileHelper.forceMkdir(location.getParentFile()); + + copy(contributionStream, location); + + // add contribution to repositoryContent + URL contributionURL = location.toURL(); + URI relative = rootFile.toURI().relativize(location.toURI()); + contributionMap.put(contribution, relative.toString()); + saveMap(); + + return contributionURL; + } + + public URL store(URI contribution, URL sourceURL) throws IOException { + // where the file should be stored in the repository + File location = mapToFile(contribution); + File source = FileHelper.toFile(sourceURL); + if (source == null || source.isFile()) { + InputStream is = sourceURL.openStream(); + try { + return store(contribution, is); + } finally { + IOHelper.closeQuietly(is); + } + } + + FileHelper.forceMkdir(location); + FileHelper.copyDirectory(source, location); + + // add contribution to repositoryContent + URI relative = rootFile.toURI().relativize(location.toURI()); + contributionMap.put(contribution, relative.toString()); + saveMap(); + + return location.toURL(); + } + + public URL find(URI contribution) { + if (contribution == null) { + return null; + } + String location = contributionMap.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(URI contribution) { + URL contributionURL = this.find(contribution); + if (contributionURL != null) { + // remove + try { + FileHelper.forceDelete(FileHelper.toFile(contributionURL)); + this.contributionMap.remove(contribution); + saveMap(); + } catch (IOException ioe) { + // handle file could not be removed + } + } + } + + public List list() { + return new ArrayList(contributionMap.keySet()); + } + + @Init + 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"); + contributionMap.put(URI.create(uri), location); + } + break; + default: + break; + } + reader.next(); + } + } catch (Exception e) { + // Ignore + } finally { + IOHelper.closeQuietly(is); + } + } + + private void saveMap() { + File domainFile = new File(rootFile, "sca-domain.xml"); + 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 : contributionMap.entrySet()) { + writer.println(" "); + } + writer.println(""); + writer.flush(); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } finally { + IOHelper.closeQuietly(os); + } + } + + @Destroy + public void destroy() { + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java new file mode 100644 index 0000000000..5d28d5f2ef --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/ContributionServiceImpl.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.util.IOHelper; +import org.apache.tuscany.host.deployment.ContributionService; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.ArtifactResolverRegistry; +import org.apache.tuscany.spi.deployer.ContributionProcessorRegistry; +import org.apache.tuscany.spi.deployer.ContributionRepository; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.DeployedArtifact; + +/** + * @version $Rev$ $Date$ + */ +public class ContributionServiceImpl implements ContributionService { + /** + * Repository where contributions are stored. Usually set by injection. + */ + protected ContributionRepository contributionRepository; + + /** + * Registry of available processors. Usually set by injection. + */ + protected ContributionProcessorRegistry processorRegistry; + + /** + * xml factory used to create reader instance to load contribution metadata + */ + protected XMLInputFactory xmlFactory; + /** + * contribution metadata loader + */ + protected ContributionLoader contributionLoader; + + + /** + * Contribution registry This is a registry of processed Contributios index + * by URI + */ + protected Map contributionRegistry = new HashMap(); + + protected ArtifactResolverRegistry resolverRegistry; + + public ContributionServiceImpl(@Autowire + ContributionRepository repository, @Autowire + ContributionProcessorRegistry processorRegistry, @Autowire + ArtifactResolverRegistry resolverRegistry) { + super(); + this.contributionRepository = repository; + this.processorRegistry = processorRegistry; + this.resolverRegistry = resolverRegistry; + + this.xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + this.contributionLoader = new ContributionLoader(null); + } + + public void contribute(URI contributionURI, URL sourceURL, boolean storeInRepository) throws DeploymentException, + 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"); + } + + addContribution(contributionURI, sourceURL, null, storeInRepository); + } + + public void contribute(URI contributionURI, InputStream input) throws DeploymentException, IOException { + addContribution(contributionURI, null, input, true); + } + + private Contribution initializeContributionMetadata(URL sourceURL) throws DeploymentException { + Contribution contributionMetadata = null; + URL contributionMetadataURL; + URL generatedContributionMetadataURL; + InputStream metadataStream = null; + + URL[] clUrls = {sourceURL}; + URLClassLoader cl = new URLClassLoader(clUrls, getClass().getClassLoader()); + + contributionMetadataURL = cl.getResource(Contribution.SCA_CONTRIBUTION_META); + generatedContributionMetadataURL = cl.getResource(Contribution.SCA_CONTRIBUTION_GENERATED_META); + + try { + if (contributionMetadataURL == null && generatedContributionMetadataURL == null) { + contributionMetadata = new Contribution(); + } else { + URL metadataURL = + contributionMetadataURL != null ? contributionMetadataURL : generatedContributionMetadataURL; + + try { + metadataStream = metadataURL.openStream(); + XMLStreamReader xmlReader = this.xmlFactory.createXMLStreamReader(metadataStream); + contributionMetadata = this.contributionLoader.load(null, null, xmlReader, null); + + } catch (IOException ioe) { + throw new + InvalidContributionMetadataException(ioe.getMessage(), metadataURL.toExternalForm(), ioe); + } catch (XMLStreamException xmle) { + throw new + InvalidContributionMetadataException(xmle.getMessage(), metadataURL.toExternalForm(), xmle); + } catch (LoaderException le) { + throw new + InvalidContributionMetadataException(le.getMessage(), metadataURL.toExternalForm(), le); + } + } + } finally { + IOHelper.closeQuietly(metadataStream); + metadataStream = null; + } + + if (contributionMetadata == null) { + contributionMetadata = new Contribution(); + } + + 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 + * @throws IOException + * @throws DeploymentException + */ + private void addContribution(URI contributionURI, URL sourceURL, InputStream contributionStream, boolean storeInRepository) + throws IOException, DeploymentException { + 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 (sourceURL != null) { + locationURL = contributionRepository.store(contributionURI, sourceURL); + } else { + locationURL = contributionRepository.store(contributionURI, contributionStream); + } + } + + Contribution contribution = initializeContributionMetadata(locationURL); + contribution.setURI(contributionURI); + contribution.setLocation(locationURL); + + if (contributionStream == null) { + contributionStream = sourceURL.openStream(); + try { + // process the contribution + this.processorRegistry.processContent(contribution, contribution.getUri(), contributionStream); + } finally { + IOHelper.closeQuietly(contributionStream); + contributionStream = null; + } + + } else { + // process the contribution + this.processorRegistry.processContent(contribution, contribution.getUri(), contributionStream); + } + + + // store the contribution on the registry + this.contributionRegistry.put(contribution.getUri(), contribution); + } + + public Object getContribution(URI id) { + return this.contributionRegistry.get(id); + } + + public void remove(URI contribution) throws DeploymentException { + // remove from repository + this.contributionRegistry.remove(contribution); + } + + public void addDeploymentComposite(URI contribution, Object composite) { + CompositeComponentType model = (CompositeComponentType)composite; + URI compositeURI = contribution.resolve(model.getName() + ".composite"); + DeployedArtifact artifact = new DeployedArtifact(compositeURI); + // FIXME: the namespace should be from the CompositeComponentType model + artifact.addModelObject(composite.getClass(), null, composite); + Contribution contributionObject = (Contribution)getContribution(contribution); + contributionObject.addArtifact(artifact); + } + + public T resolve(URI contribution, Class definitionType, String namespace, String name) { + Contribution contributionObject = (Contribution)getContribution(contribution); + return resolverRegistry.resolve(contributionObject, definitionType, namespace, name, null, null); + } + + public URL resolve(URI contribution, String namespace, URI uri, URI baseURI) { + Contribution contributionObject = (Contribution)getContribution(contribution); + return resolverRegistry.resolve(contributionObject, namespace, uri.toString(), baseURI.toString()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/DomainUpdateException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/DomainUpdateException.java new file mode 100644 index 0000000000..65df12f35c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/DomainUpdateException.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment; + +import org.apache.tuscany.host.deployment.DeploymentException; + +public class DomainUpdateException extends DeploymentException { + public DomainUpdateException() { + } + + public DomainUpdateException(String message) { + super(message); + } + + public DomainUpdateException(String message, String identifier) { + super(message, identifier); + } + + public DomainUpdateException(String message, Throwable cause) { + super(message, cause); + } + + public DomainUpdateException(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } + + public DomainUpdateException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidContributionMetadataException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidContributionMetadataException.java new file mode 100644 index 0000000000..110633e685 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidContributionMetadataException.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment; + +import org.apache.tuscany.host.deployment.DeploymentException; + +/** + * Exception that indicates that the supplied XML Document invalid. + * + * @version $Rev: 511466 $ $Date: 2007-02-25 00:45:22 -0800 (Sun, 25 Feb 2007) $ + */ +public class InvalidContributionMetadataException extends DeploymentException { + + protected InvalidContributionMetadataException() { + } + + protected InvalidContributionMetadataException(String message) { + super(message); + } + + protected InvalidContributionMetadataException(String message, String identifier) { + super(message, identifier); + } + + protected InvalidContributionMetadataException(String message, Throwable cause) { + super(message, cause); + } + + protected InvalidContributionMetadataException(String message, String identifier, Throwable cause) { + super(message, identifier, cause); + } + + protected InvalidContributionMetadataException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java new file mode 100644 index 0000000000..c4848a3a08 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/InvalidDocumentException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment; + +import org.apache.tuscany.host.deployment.DeploymentException; + +/** + * Exception that indicates that the supplied XML Document invalid. + * + * @version $Rev$ $Date$ + */ +public class InvalidDocumentException extends DeploymentException { + + /** + * + */ + private static final long serialVersionUID = 8872656291809499499L; + + protected InvalidDocumentException(String rootElement) { + super(rootElement); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java new file mode 100644 index 0000000000..87f68340e2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/XMLChangeSetHandler.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment; + +import java.io.IOException; +import java.io.InputStream; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.builder.Builder; +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.ComponentRegistrationException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.PrepareException; +import org.apache.tuscany.spi.deployer.ChangeSetHandler; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.Loader; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; + +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.host.deployment.ContentTypes; +import org.apache.tuscany.host.deployment.DeploymentException; + +/** + * @version $Rev$ $Date$ + */ +public class XMLChangeSetHandler implements ChangeSetHandler { + private static final String NS = "http://tuscany.apache.org/xmlns/1.0-SNAPSHOT"; + private static final QName CHANGESET = new QName(NS, "changeSet"); + private static final QName CREATECOMPONENT = new QName(NS, "createComponent"); + + private final RuntimeComponent runtime; + private final Builder builder; + private final Loader loader; + private final XMLInputFactory xmlFactory; + + public XMLChangeSetHandler(RuntimeComponent runtime, Loader loader, Builder builder) { + this.runtime = runtime; + this.loader = loader; + this.builder = builder; + xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + } + + public String getContentType() { + return ContentTypes.CHANGESET_XML; + } + + public void applyChanges(InputStream changeSet) throws DeploymentException, IOException { + try { + XMLStreamReader xmlReader = xmlFactory.createXMLStreamReader(changeSet); + while (true) { + switch (xmlReader.next()) { + case START_ELEMENT: + if (!CHANGESET.equals(xmlReader.getName())) { + throw new InvalidDocumentException(xmlReader.getName().toString()); + } + processChanges(xmlReader); + break; + case END_DOCUMENT: + return; + } + } + } catch (XMLStreamException e) { + throw (IOException) new IOException(e.getMessage()).initCause(e); + } + } + + public void processChanges(XMLStreamReader xmlReader) throws XMLStreamException, DeploymentException { + while (true) { + switch (xmlReader.next()) { + case START_ELEMENT: + if (CREATECOMPONENT.equals(xmlReader.getName())) { + createComponent(xmlReader); + } else { + // reject unrecognized commands + throw new InvalidDocumentException(xmlReader.getName().toString()); + } + break; + case END_ELEMENT: + return; + } + } + } + + public void createComponent(XMLStreamReader xmlReader) throws XMLStreamException { + DeploymentContext deploymentContext = new RootDeploymentContext(null, xmlFactory, null, null); + CompositeComponent parent = runtime.getRootComponent(); + try { + ComponentDefinition componentDefinition = + (ComponentDefinition) loader.load(parent, null, xmlReader, deploymentContext); + Component component = builder.build(parent, componentDefinition, deploymentContext); + component.prepare(); + parent.register(component); + } catch (LoaderException e) { + // FIXME throw something appropriate + throw new AssertionError("FIXME"); + } catch (BuilderException e) { + // FIXME throw something appropriate + throw new AssertionError("FIXME"); + } catch (PrepareException e) { + // FIXME throw something appropriate + throw new AssertionError("FIXME"); + } catch (ComponentRegistrationException e) { + // FIXME throw something appropriate + throw new AssertionError("FIXME"); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/CompositeContributionProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/CompositeContributionProcessor.java new file mode 100644 index 0000000000..8309273b3f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/CompositeContributionProcessor.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.core.services.deployment.contribution; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.ContentType; +import org.apache.tuscany.spi.deployer.ContributionProcessor; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.model.Contribution; + +public class CompositeContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor { + /** + * Content-type that this processor can handle + */ + public static final String CONTENT_TYPE = ContentType.COMPOSITE; + + protected XMLInputFactory xmlFactory; + private final LoaderRegistry registry; + + public CompositeContributionProcessor(@Autowire LoaderRegistry registry) { + super(); + this.registry = registry; + this.xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + } + + @Override + public String getContentType() { + return CONTENT_TYPE; + } + + public void processContent(Contribution contribution, URI artifactURI, InputStream inputStream) + throws DeploymentException, IOException { + if (artifactURI == null) { + throw new IllegalArgumentException("Invalid null source uri."); + } + + if (inputStream == null) { + throw new IllegalArgumentException("Invalid null source inputstream."); + } + + try { + CompositeClassLoader cl = new CompositeClassLoader(getClass().getClassLoader()); + cl.addURL(contribution.getLocation()); + DeploymentContext deploymentContext = new RootDeploymentContext(cl, this.xmlFactory, null, + contribution.getArtifact(artifactURI).getLocation()); + + CompositeComponentType componentType = this.registry.load(null, null, + contribution.getArtifact(artifactURI).getLocation(), + CompositeComponentType.class, deploymentContext); + + CompositeImplementation implementation = new CompositeImplementation(); + implementation.setComponentType(componentType); + ComponentDefinition componentDefinition = + new ComponentDefinition(implementation); + + componentDefinition.setName(componentType.getName()); + + contribution.getArtifact(artifactURI).addModelObject(CompositeComponentType.class, null, componentDefinition); + + } catch (LoaderException le) { + throw new InvalidComponentDefinitionlException(contribution.getArtifact(artifactURI).getLocation() + .toExternalForm(), le); + } + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.java new file mode 100644 index 0000000000..3bcfefb1ca --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/FolderContributionProcessor.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.core.services.deployment.contribution; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.core.services.deployment.ContentTypeDescriberImpl; +import org.apache.tuscany.core.util.FileHelper; +import org.apache.tuscany.core.util.IOHelper; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.deployer.ContentType; +import org.apache.tuscany.spi.deployer.ContentTypeDescriber; +import org.apache.tuscany.spi.deployer.ContributionProcessor; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.DeployedArtifact; + +public class FolderContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor { + /** + * Content-type that this processor can handle + */ + public static final String CONTENT_TYPE = ContentType.FOLDER; + + @Override + public String getContentType() { + return CONTENT_TYPE; + } + + /** + * Recursively traverse a root directory + * + * @param fileList + * @param root + * @throws IOException + */ + private void traverse(List fileList, File root) throws IOException { + if (root.isFile()) { + fileList.add(root.toURL()); + } else if (root.isDirectory()) { + // FIXME: Maybe we should externalize it as a property + // Regular expression to exclude .xxx files + File[] files = root.listFiles(FileHelper.getFileFilter("[^\u002e].*", true)); + for (int i = 0; i < files.length; i++) { + traverse(fileList, files[i]); + } + } + } + + /** + * Get a list of files from the directory + * + * @return + * @throws IOException + */ + protected List getArtifacts(URL rootURL) throws DeploymentException, + IOException { + List artifacts = new ArrayList(); + + // Assume the root is a jar file + File rootFolder; + + try { + rootFolder = new File(rootURL.toURI()); + if (rootFolder.isDirectory()) { + this.traverse(artifacts, rootFolder); + } + + } catch (URISyntaxException e) { + throw new InvalidFolderContributionURIException(rootURL.toExternalForm(), e); + } + + return artifacts; + } + + public void processContent(Contribution contribution, URI source, InputStream inputStream) + throws DeploymentException, IOException { + if (contribution == null) { + throw new IllegalArgumentException("Invalid null contribution."); + } + + if (source == null) { + throw new IllegalArgumentException("Invalid null source uri."); + } + + URL contributionURL = contribution.getArtifact(source).getLocation(); + + for (URL artifactURL : getArtifacts(contributionURL)) { + String artifactPath = artifactURL.toExternalForm().substring(contributionURL.toExternalForm().length()); + URI artifactURI = contribution.getUri().resolve(artifactPath); + DeployedArtifact artifact = new DeployedArtifact(artifactURI); + artifact.setLocation(artifactURL); + contribution.addArtifact(artifact); + + ContentTypeDescriber contentTypeDescriber = new ContentTypeDescriberImpl(); + String contentType = contentTypeDescriber.getContentType(artifactURL, null); + + // just process scdl and contribution metadata for now + if (ContentType.COMPOSITE.equals(contentType)) { + InputStream is = artifactURL.openStream(); + try { + this.registry.processContent(contribution, artifactURI, is); + } finally { + IOHelper.closeQuietly(is); + is = null; + } + } + } + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + // NOOP + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java new file mode 100644 index 0000000000..c5c7d8cbf9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidComponentDefinitionlException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment.contribution; + +import org.apache.tuscany.host.deployment.DeploymentException; + +/** + * Exception that indicates that the supplied XML Document invalid. + * + */ +public class InvalidComponentDefinitionlException extends DeploymentException { + + /** + * + */ + private static final long serialVersionUID = 2724173457894813837L; + + protected InvalidComponentDefinitionlException(String componentDefinitionLocatoin) { + super(componentDefinitionLocatoin); + } + + protected InvalidComponentDefinitionlException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java new file mode 100644 index 0000000000..0e6ff6b5e8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidFolderContributionURIException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment.contribution; + +import org.apache.tuscany.host.deployment.DeploymentException; + +/** + * + */ +public class InvalidFolderContributionURIException extends DeploymentException { + + /** + * + */ + private static final long serialVersionUID = 1564255850052593282L; + + protected InvalidFolderContributionURIException(String componentDefinitionLocatoin) { + super(componentDefinitionLocatoin); + } + + protected InvalidFolderContributionURIException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidPojoComponentDefinitionlException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidPojoComponentDefinitionlException.java new file mode 100644 index 0000000000..e2d2f12cb5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/InvalidPojoComponentDefinitionlException.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.deployment.contribution; + +import org.apache.tuscany.host.deployment.DeploymentException; + +/** + * Exception that indicates that the supplied XML Document invalid. + * + */ +public class InvalidPojoComponentDefinitionlException extends DeploymentException { + + protected InvalidPojoComponentDefinitionlException(String componentDefinitionLocatoin) { + super(componentDefinitionLocatoin); + } + + protected InvalidPojoComponentDefinitionlException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java new file mode 100644 index 0000000000..819c0ce9e6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JarContributionProcessor.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment.contribution; + +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.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +import org.apache.tuscany.core.services.deployment.ContentTypeDescriberImpl; +import org.apache.tuscany.core.util.IOHelper; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.deployer.ContentType; +import org.apache.tuscany.spi.deployer.ContentTypeDescriber; +import org.apache.tuscany.spi.deployer.ContributionProcessor; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.DeployedArtifact; + +public class JarContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor { + /** + * Content-type that this processor can handle + */ + public static final String CONTENT_TYPE = ContentType.JAR; + + @Override + public String getContentType() { + return CONTENT_TYPE; + } + + /** + * Get a list of resources inside the jar + * + * @return + * @throws IOException + */ + protected List getArtifacts(URL rootURL, InputStream sourceInputStream) throws IOException { + List artifacts = new ArrayList(); + + // Assume the root is a jar file + JarInputStream jar = new JarInputStream(sourceInputStream); + try { + while (true) { + JarEntry entry = jar.getNextJarEntry(); + if (entry == null) { + // EOF + break; + } + if (entry.isDirectory()) { + continue; + } + + // FIXME: Maybe we should externalize the filter as a property + if (!entry.getName().startsWith(".")) { + artifacts.add(new URL(rootURL, entry.getName())); + } + } + } finally { + jar.close(); + } + return artifacts; + } + + private URL forceJarURL(URL sourceURL) throws MalformedURLException { + if (sourceURL.toString().startsWith("jar:")) { + return sourceURL; + } else { + return new URL("jar:" + sourceURL.toExternalForm() + "!/"); + } + + } + + public void processContent(Contribution contribution, URI source, InputStream inputStream) + throws DeploymentException, IOException { + if (contribution == null) { + throw new IllegalArgumentException("Invalid null contribution."); + } + + if (source == null) { + throw new IllegalArgumentException("Invalid null source uri."); + } + + if (inputStream == null) { + throw new IllegalArgumentException("Invalid null source inputstream."); + } + + URL sourceURL = contribution.getArtifact(source).getLocation(); + + sourceURL = forceJarURL(sourceURL); + + for (URL artifactURL : getArtifacts(sourceURL, inputStream)) { + URI artifactURI; + + String artifactPath = artifactURL.toExternalForm().substring(sourceURL.toExternalForm().length()); + artifactURI = contribution.getUri().resolve(artifactPath); + DeployedArtifact artifact = new DeployedArtifact(artifactURI); + artifact.setLocation(artifactURL); + contribution.addArtifact(artifact); + + + ContentTypeDescriber contentTypeDescriber = new ContentTypeDescriberImpl(); + String contentType = contentTypeDescriber.getContentType(artifactURL, null); + + // just process scdl for now + if (ContentType.COMPOSITE.equals(contentType)) { + InputStream is = IOHelper.getInputStream(artifactURL); + try { + this.registry.processContent(contribution, artifactURI, is); + } finally { + IOHelper.closeQuietly(is); + is = null; + } + } + } + + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + // TODO Auto-generated method stub + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java new file mode 100644 index 0000000000..0a95dcc684 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/JavaContributionProcessor.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment.contribution; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; + +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.ContentType; +import org.apache.tuscany.spi.deployer.ContributionProcessor; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Contribution; +import org.osoa.sca.annotations.Constructor; + +public class JavaContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor { + /** + * Content-type that this processor can handle + */ + public static final String CONTENT_TYPE = ContentType.JAVA; + /** + * Pojo introspector + */ + private Introspector introspector; + + @Constructor("introspector") + public JavaContributionProcessor(@Autowire IntrospectionRegistry introspector) { + this.introspector = introspector; + } + + @Override + public String getContentType() { + return CONTENT_TYPE; + } + + private String getClazzName(URL clazzURL) { + String clazzName; + + clazzName = + clazzURL.toExternalForm().substring(clazzURL.toExternalForm().lastIndexOf("!/") + 2, + clazzURL.toExternalForm().length() - ".class".length()); + clazzName = clazzName.replace("/", "."); + + return clazzName; + } + + public void processContent(Contribution contribution, URI artifactURI, InputStream inputStream) + throws DeploymentException, IOException { + if (artifactURI == null) { + throw new IllegalArgumentException("Invalid null source uri."); + } + + if (inputStream == null) { + throw new IllegalArgumentException("Invalid null source inputstream."); + } + + try { + CompositeClassLoader cl = new CompositeClassLoader(getClass().getClassLoader()); + cl.addURL(contribution.getLocation()); + + String clazzName = getClazzName(contribution.getArtifact(artifactURI).getLocation()); + + Class clazz = cl.loadClass(clazzName); + + PojoComponentType javaInfo = introspector.introspect(null, clazz, null, null); + + contribution.getArtifact(artifactURI).addModelObject(PojoComponentType.class, null, javaInfo); + + } catch (ClassNotFoundException cnfe) { + throw new InvalidPojoComponentDefinitionlException(contribution.getArtifact(artifactURI).getLocation() + .toExternalForm(), cnfe); + } catch (ProcessingException pe) { + throw new InvalidPojoComponentDefinitionlException(contribution.getArtifact(artifactURI).getLocation() + .toExternalForm(), pe); + } + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + // NOOP + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/MetadataContributionProcessor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/MetadataContributionProcessor.java new file mode 100644 index 0000000000..63d8320860 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/contribution/MetadataContributionProcessor.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment.contribution; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.services.deployment.ContributionLoader; +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.deployer.ContentType; +import org.apache.tuscany.spi.deployer.ContributionProcessor; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.Contribution; + +public class MetadataContributionProcessor extends ContributionProcessorExtension implements ContributionProcessor { + /** + * Content-type that this processor can handle + */ + public static final String CONTENT_TYPE = ContentType.CONTRIBUTION_METADATA; + + protected XMLInputFactory xmlFactory; + protected ContributionLoader contributionLoader; + + public MetadataContributionProcessor() { + super(); + this.xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + this.contributionLoader = new ContributionLoader(null); + } + + @Override + public String getContentType() { + return CONTENT_TYPE; + } + + public void processContent(Contribution contribution, URI artifactURI, InputStream inputStream) + throws DeploymentException, IOException { + if (artifactURI == null) { + throw new IllegalArgumentException("Invalid null source uri."); + } + + if (inputStream == null) { + throw new IllegalArgumentException("Invalid null source inputstream."); + } + + try { + XMLStreamReader xmlReader = this.xmlFactory.createXMLStreamReader(inputStream); + Contribution contributionMetadata = this.contributionLoader.load(null, null, xmlReader, null); + + for (QName deployable : contributionMetadata.getDeployables()) { + System.out.println("Deployable : " + deployable.toString()); + } + + } catch (XMLStreamException xmle) { + throw new InvalidComponentDefinitionlException(contribution.getArtifact(artifactURI).getLocation() + .toExternalForm(), xmle); + } catch (LoaderException le){ + throw new InvalidComponentDefinitionlException(contribution.getArtifact(artifactURI).getLocation() + .toExternalForm(), le); + } + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/resolver/ComponentDefinitionArtifactResolver.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/resolver/ComponentDefinitionArtifactResolver.java new file mode 100644 index 0000000000..27586a322e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/deployment/resolver/ComponentDefinitionArtifactResolver.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.services.deployment.resolver; + +import java.net.URI; +import java.net.URL; +import java.util.Map; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.ArtifactResolver; +import org.apache.tuscany.spi.deployer.ArtifactResolverRegistry; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ArtifactResolverExtension; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.DeployedArtifact; + +public class ComponentDefinitionArtifactResolver extends ArtifactResolverExtension implements ArtifactResolver { + + public ComponentDefinitionArtifactResolver(@Autowire + ArtifactResolverRegistry registry) { + super(registry); + } + + @Override + public Class getType() { + return ComponentDefinition.class; + } + + public ComponentDefinition resolve(Contribution contribution, + Class modelClass, + String namespace, + String name, + Map attributes, + DeploymentContext context) { + + // generate artifact uri based on it's name + URI artifactURI = contribution.getUri().resolve(name); + DeployedArtifact artifact = contribution.getArtifact(artifactURI); + + ComponentDefinition componentDefinition = + (ComponentDefinition)artifact.getModelObject(CompositeComponentType.class, null); + return componentDefinition; + } + + public URL resolve(Contribution contribution, String targetNamespace, String location, String baseURI) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java new file mode 100644 index 0000000000..cc3339e2b7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.extension; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ComponentException; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.builder.BuilderException; + +/** + * @version $Rev$ $Date$ + */ +public class AbstractExtensionDeployer { + protected Deployer deployer; + protected CompositeComponent parent; + + @Autowire + public void setDeployer(Deployer deployer) { + this.deployer = deployer; + } + + @Autowire + public void setParent(CompositeComponent parent) { + this.parent = parent; + } + + protected void deployExtension(File file) { + // extension name is file name less any extension + String name = file.getName(); + int dot = name.lastIndexOf('.'); + if (dot > 0) { + name = name.substring(0, dot); + } + URL url; + try { + url = file.toURI().toURL(); + } catch (MalformedURLException e) { + // toURI should have encoded the URL + throw new AssertionError(); + } + + deployExtension(name, url); + } + + protected void deployExtension(String name, URL url) { + // FIXME for now, assume this class's ClassLoader is the Tuscany system classloader + // FIXME we should really use the one associated with the parent composite + CompositeClassLoader extensionCL = new CompositeClassLoader(getClass().getClassLoader()); + + // see if the URL points to a composite JAR by looking for a default SCDL file inside it + URL scdlLocation; + try { + scdlLocation = new URL("jar:" + url.toExternalForm() + "!/META-INF/sca/default.scdl"); + } catch (MalformedURLException e) { + // the form of the jar: URL should be correct given url.toExternalForm() worked + throw new AssertionError(); + } + try { + scdlLocation.openStream().close(); + // we connected to the SCDL so let's add the JAR file to the classloader + extensionCL.addURL(url); + } catch (IOException e) { + // assume that the URL we were given is not a JAR file so just use the supplied resource + scdlLocation = url; + } + + // create a ComponentDefinition to represent the component we are going to deploy + SystemCompositeImplementation implementation = new SystemCompositeImplementation(); + implementation.setScdlLocation(scdlLocation); + implementation.setClassLoader(extensionCL); + ComponentDefinition definition = + new ComponentDefinition(name, implementation); + + // FIXME: [rfeng] Should we reset the thread context class loader here? + // From the debugger with tomcat, the current TCCL is the RealmClassLoader + // ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + try { + // Thread.currentThread().setContextClassLoader(extensionCL); + Component component = null; + try { + component = deployer.deploy(parent, definition); + component.start(); + } catch (BuilderException e) { + // FIXME JFM handle the exception + e.printStackTrace(); + } catch (ComponentException e) { + // FIXME handle the exception + e.printStackTrace(); + } + } catch (LoaderException e) { + // FIXME handle the exception + e.printStackTrace(); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java new file mode 100644 index 0000000000..38ce4d16d2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/host/DelegatingResourceHostRegistry.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.host; + +import java.util.HashMap; +import java.util.Map; + +import org.osoa.sca.annotations.Service; + +import org.apache.tuscany.spi.host.ResourceHost; +import org.apache.tuscany.spi.host.ResourceHostRegistry; +import org.apache.tuscany.spi.host.ResourceResolutionException; + +/** + * The default implementation of a ResourceRegisty that resolves resources in the SCA:// + * namespace against its parent composite and delegates resolution to registered ResourceHosts for other + * namespaces. The search order for resources resolved by type starts with the SCA namespace and proceeds to hosts in + * the order they were registered. + * + * @version $Rev$ $Date$ + */ +@Service(interfaces = {ResourceHost.class, ResourceHostRegistry.class}) +public class DelegatingResourceHostRegistry implements ResourceHost, ResourceHostRegistry { + private static final String SCA_PREFIX = "SCA://"; + private Map resourceHosts = new HashMap(); + private Map, Object> systemResources = new HashMap, Object>(); + private Map mappedSystemResources = new HashMap(); + + public DelegatingResourceHostRegistry() { + } + + public void registerResourceHost(String uri, ResourceHost host) { + resourceHosts.put(uri, host); + } + + public void unregisterResourceHost(String uri) { + resourceHosts.remove(uri); + } + + public void registerResource(Class type, Object resource) { + systemResources.put(type, resource); + } + + public void registerResource(Class type, String name, Object resource) { + mappedSystemResources.put(new Key(type, name), resource); + } + + public void unregisterResource(Class type, String name) { + mappedSystemResources.remove(new Key(type, name)); + } + + public void unregisterResource(Class type) { + systemResources.remove(type); + } + + public T resolveResource(Class type) throws ResourceResolutionException { + T instance = type.cast(systemResources.get(type)); + if (instance == null) { + for (ResourceHost host : resourceHosts.values()) { + instance = host.resolveResource(type); + if (instance != null) { + return instance; + } + } + } + return instance; + } + + public T resolveResource(Class type, String mappedName) throws ResourceResolutionException { + if (mappedName.startsWith(SCA_PREFIX)) { + String name = mappedName.substring(SCA_PREFIX.length()); + return type.cast(mappedSystemResources.get(new Key(type, name))); + } else { + int pos = mappedName.indexOf("://"); + if (pos == -1) { + return type.cast(mappedSystemResources.get(new Key(type, mappedName))); + } + String uri = mappedName.substring(0, pos + 3); + ResourceHost host = resourceHosts.get(uri); + if (host == null) { + throw new ResourceResolutionException("No resource host for URI", uri); + } + return host.resolveResource(type, mappedName); + } + } + + private class Key { + private Class clazz; + private String name; + + public Key(Class clazz, String name) { + this.clazz = clazz; + this.name = name; + } + + public Key(Class clazz) { + this.clazz = clazz; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Key key = (Key) o; + + if (clazz != null ? !clazz.equals(key.clazz) : key.clazz != null) { + return false; + } + if (name != null ? !name.equals(key.name) : key.name != null) { + return false; + } + return true; + } + + public int hashCode() { + int result; + result = clazz != null ? clazz.hashCode() : 0; + result = 31 * result + (name != null ? name.hashCode() : 0); + return result; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java new file mode 100644 index 0000000000..b1a0b67001 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/store/memory/MemoryStore.java @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.store.memory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.EagerInit; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Service; + +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.event.AbstractEventPublisher; +import org.apache.tuscany.spi.services.store.DuplicateRecordException; +import org.apache.tuscany.spi.services.store.RecoveryListener; +import org.apache.tuscany.spi.services.store.Store; +import org.apache.tuscany.spi.services.store.StoreExpirationEvent; +import org.apache.tuscany.spi.services.store.StoreMonitor; +import org.apache.tuscany.spi.services.store.StoreWriteException; + +import org.apache.tuscany.api.annotation.Monitor; + +/** + * Implements a non-durable, non-transactional store using a simple in-memory map + * + * @version $Rev$ $Date$ + */ +@Service(Store.class) +@EagerInit +public class MemoryStore extends AbstractEventPublisher implements Store { + private Map> store; + // TODO integrate with a core threading scheme + private ScheduledExecutorService scheduler; + private long reaperInterval = 300000; + private StoreMonitor monitor; + private long defaultExpirationOffset = 600000; // 10 minutes + + public MemoryStore(@Monitor StoreMonitor monitor) { + this.monitor = monitor; + this.store = new ConcurrentHashMap>(); + this.scheduler = Executors.newSingleThreadScheduledExecutor(); + } + + /** + * Returns the maximum default expiration offset for records in the store + * + * @return the maximum default expiration offset for records in the store + */ + public long getDefaultExpirationOffset() { + return defaultExpirationOffset; + } + + /** + * Sets the maximum default expiration offset for records in the store + */ + @Property + public void setDefaultExpirationOffset(long defaultExpirationOffset) { + this.defaultExpirationOffset = defaultExpirationOffset; + } + + /** + * Sets the interval for expired entry scanning to be performed + */ + @Property + public void setReaperInterval(long reaperInterval) { + this.reaperInterval = reaperInterval; + } + + public long getReaperInterval() { + return reaperInterval; + } + + @Init + public void init() { + scheduler.scheduleWithFixedDelay(new Reaper(), reaperInterval, reaperInterval, TimeUnit.MILLISECONDS); + monitor.start("In-memory store started"); + } + + @Destroy + public void destroy() { + scheduler.shutdown(); + monitor.stop("In-memory store stopped"); + } + + public void insertRecord(SCAObject owner, String id, Object object, long expiration) throws StoreWriteException { + Map map = store.get(owner); + if (map == null) { + map = new ConcurrentHashMap(); + store.put(owner, map); + } + if (map.containsKey(id)) { + throw new DuplicateRecordException(owner.getCanonicalName(), id); + } + map.put(id, new Record(object, expiration)); + } + + public void updateRecord(SCAObject owner, String id, Object object, long expiration) throws StoreWriteException { + Map map = store.get(owner); + if (map == null) { + throw new StoreWriteException("Record not found", owner.getCanonicalName(), id); + } + Record record = map.get(id); + if (record == null) { + throw new StoreWriteException("Record not found", owner.getCanonicalName(), id); + } + record.data = object; + } + + public Object readRecord(SCAObject owner, String id) { + Map map = store.get(owner); + if (map == null) { + return null; + } + Record record = map.get(id); + if (record != null) { + return record.data; + } + return null; + } + + public void removeRecords() { + store.clear(); + } + + public void removeRecord(SCAObject owner, String id) throws StoreWriteException { + Map map = store.get(owner); + if (map == null) { + throw new StoreWriteException("Owner not found", owner.getCanonicalName(), id); + } + if (map.remove(id) == null) { + throw new StoreWriteException("Owner not found", owner.getCanonicalName(), id); + } + } + + public void recover(RecoveryListener listener) { + throw new UnsupportedOperationException(); + } + + private class Record { + private Object data; + private long expiration = NEVER; + + public Record(Object data, long expiration) { + this.data = data; + this.expiration = expiration; + } + + public Object getData() { + return data; + } + + public long getExpiration() { + return expiration; + } + } + + private class Reaper implements Runnable { + + public void run() { + long now = System.currentTimeMillis(); + for (Map.Entry> entries : store.entrySet()) { + for (Map.Entry entry : entries.getValue().entrySet()) { + final long expiration = entry.getValue().expiration; + if (expiration != NEVER && now >= expiration) { + SCAObject owner = entries.getKey(); + Object instance = entry.getValue().getData(); + // notify listeners of the expiration + StoreExpirationEvent event = new StoreExpirationEvent(this, owner, instance); + publish(event); + entries.getValue().remove(entry.getKey()); + } + } + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java new file mode 100644 index 0000000000..79b7bf4ca1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jca; + +import javax.resource.spi.work.Work; +import javax.resource.spi.work.WorkEvent; +import javax.resource.spi.work.WorkException; +import javax.resource.spi.work.WorkListener; +import javax.resource.spi.work.WorkManager; +import javax.resource.spi.work.WorkRejectedException; + +import org.apache.tuscany.spi.services.work.NotificationListener; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.services.work.WorkSchedulerException; + +/** + * A work scheduler implementation based on the JCA SPI work manager. + *

      + *

      + * This needs a JCA SPI work manager implementation available for scheduling work. Instances can be configured with a + * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work + * manager implementaion available.

      + */ +public class JcaWorkScheduler implements WorkScheduler { + + /** + * Underlying JCA work manager + */ + private WorkManager jcaWorkManager; + + /** + * Initializes the JCA work manager. + * + * @param jcaWorkManager JCA work manager. + */ + public JcaWorkScheduler(WorkManager jcaWorkManager) { + + if (jcaWorkManager == null) { + throw new IllegalArgumentException("Work manager cannot be null"); + } + this.jcaWorkManager = jcaWorkManager; + + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + */ + public 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"); + } + + JcaWork jcaWork = new JcaWork(work); + try { + if (listener == null) { + jcaWorkManager.scheduleWork(jcaWork); + } else { + JcaWorkListener jcaWorkListener = new JcaWorkListener(listener); + // TODO Clarify the usage of timeout and execution context + jcaWorkManager.scheduleWork(jcaWork, -1, null, jcaWorkListener); + } + } catch (WorkRejectedException ex) { + if (listener != null) { + listener.workRejected(work); + } else { + throw new WorkSchedulerException(ex); + } + } catch (WorkException ex) { + throw new WorkSchedulerException(ex); + } + + } + + /* + * Worklistener for keeping track of work status callbacks. + * + */ + private class JcaWorkListener implements WorkListener { + + // Notification listener + private NotificationListener listener; + + /* + * Initializes the notification listener. + */ + public JcaWorkListener(NotificationListener listener) { + this.listener = listener; + } + + /* + * Callback when the work is accepted. + */ + public void workAccepted(WorkEvent workEvent) { + T work = getWork(workEvent); + listener.workAccepted(work); + } + + /* + * Callback when the work is rejected. + */ + public void workRejected(WorkEvent workEvent) { + T work = getWork(workEvent); + listener.workRejected(work); + } + + /* + * Callback when the work is started. + */ + public void workStarted(WorkEvent workEvent) { + T work = getWork(workEvent); + listener.workStarted(work); + } + + /* + * Callback when the work is completed. + */ + public void workCompleted(WorkEvent workEvent) { + T work = getWork(workEvent); + Exception exception = workEvent.getException(); + if (exception != null) { + listener.workFailed(work, exception); + } else { + listener.workCompleted(work); + } + } + + /* + * Gets the underlying work from the work event. + */ + @SuppressWarnings("unchecked") + private T getWork(WorkEvent workEvent) { + JcaWork jcaWork = (JcaWork) workEvent.getWork(); + return jcaWork.getWork(); + } + + } + + /* + * JCA work wrapper. + */ + private class JcaWork implements Work { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public JcaWork(T work) { + this.work = work; + } + + /* + * Releases the work. + */ + public void release() { + } + + /* + * Performs the work. + */ + public void run() { + work.run(); + } + + /* + * Returns the completed work. + */ + public T getWork() { + return work; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java new file mode 100644 index 0000000000..8fa8000477 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237; + +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.services.work.NotificationListener; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.services.work.WorkSchedulerException; + +import commonj.work.Work; +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkListener; +import commonj.work.WorkManager; +import commonj.work.WorkRejectedException; + +/** + * A work scheduler implementation based on a JSR 237 work manager. + *

      + *

      + * This needs a JSR 237 work manager implementation available for scheduling work. Instances can be configured with a + * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work + * manager implementaion available. For example, if the managed environment supports work manager the runtime can use + * the appropriate lookup mechanism to inject the work manager implementation.

      + */ +@Scope("COMPOSITE") +public class Jsr237WorkScheduler implements WorkScheduler { + + /** + * Underlying JSR-237 work manager + */ + private WorkManager jsr237WorkManager; + + /** + * Initializes the JSR 237 work manager. + * + * @param jsr237WorkManager JSR 237 work manager. + */ + public Jsr237WorkScheduler(@Autowire WorkManager jsr237WorkManager) { + if (jsr237WorkManager == null) { + throw new IllegalArgumentException("Work manager cannot be null"); + } + this.jsr237WorkManager = jsr237WorkManager; + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + */ + public 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 (WorkRejectedException ex) { + if (listener != null) { + listener.workRejected(work); + } else { + throw new WorkSchedulerException(ex); + } + } catch (WorkException ex) { + throw new WorkSchedulerException(ex); + } + + } + + /* + * Worklistener for keeping track of work status callbacks. + * + */ + private class Jsr237WorkListener 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; + } + + } + + /* + * JCA work wrapper. + */ + private class Jsr237Work implements Work { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public Jsr237Work(T work) { + this.work = work; + } + + /* + * Returns the completed work. + */ + public T getWork() { + return work; + } + + /* + * Release the work. + */ + public void release() { + } + + /* + * Work attributes are not daemon. + */ + public boolean isDaemon() { + return false; + } + + /* + * Runs the work. + */ + public void run() { + work.run(); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java new file mode 100644 index 0000000000..c391d0b597 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkItem; + +/** + * Default immutable implementation of the WorkEvent class. + */ +class DefaultWorkEvent implements WorkEvent { + + // Work item for this event + private WorkItem workItem; + + // Exception if something has gone wrong + private WorkException exception; + + /** + * Instantiates the event. + * + * @param workItem Work item for this event. + */ + public DefaultWorkEvent(final DefaultWorkItem workItem) { + this.workItem = workItem; + this.exception = workItem.getException(); + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work type. + */ + public int getType() { + return workItem.getStatus(); + } + + /** + * Returns the work item associated with this work type. + * + * @return Work item. + */ + public WorkItem getWorkItem() { + return workItem; + } + + /** + * Returns the exception if the work completed with an exception. + * + * @return Work exception. + */ + public WorkException getException() { + return exception; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java new file mode 100644 index 0000000000..0adc005bb0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import commonj.work.Work; +import commonj.work.WorkException; +import commonj.work.WorkItem; + +/** + * An identity based immutable implementation of the WorkItem + * interface. + * + */ +class DefaultWorkItem implements WorkItem { + + // Id scoped for the VM + private String id; + + // Status + private int status = -1; + + // Result + private Work result; + + // Original work + private Work originalWork; + + // Exception + private WorkException exception; + + /** + * Instantiates an id for this item. + * + * @param id of this work event. + */ + protected DefaultWorkItem(final String id, final Work orginalWork) { + this.id = id; + this.originalWork = orginalWork; + } + + /** + * Returns the id. + * + * @return Id of this item. + */ + public String getId() { + return id; + } + + /** + * Returns the original work. + * + * @return Original work. + */ + public Work getOriginalWork() { + return originalWork; + } + + /** + * Returns the work result if the work completed. + * + * @return Work. + * @throws WorkException If the work completed with an exception. + */ + public Work getResult() throws WorkException { + return result; + } + + /** + * Sets the result. + * + * @param result Result. + */ + protected void setResult(final Work result) { + this.result = result; + } + + /** + * Returns the exception if work completed with an exception. + * + * @return Work exception. + */ + protected WorkException getException() { + return exception; + } + + /** + * Sets the exception. + * + * @param exception Exception. + */ + protected void setException(final WorkException exception) { + this.exception = exception; + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work status. + */ + public int getStatus() { + return status; + } + + /** + * Sets the status. + * + * @param status Status. + */ + protected void setStatus(final int status) { + this.status = status; + } + + /** + * @see Object#hashCode() + */ + public int hashCode() { + return id.hashCode(); + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param obj Object to be compared. + * @return true if this object is the same as the obj argument; false + * otherwise.. + */ + public boolean equals(final Object obj) { + return (obj != null) && (obj.getClass() == DefaultWorkItem.class) && ((DefaultWorkItem) obj).id.equals(id); + } + + /** + * Compares this object with the specified object for order. Returns a + * negative integer, zero, or a positive integer as this object is less + * than, equal to, or greater than the specified object. + * + * @param o Object to be compared. + * @return A negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + * @throws ClassCastException needs better documentation. + */ + public int compareTo(final Object o) { + if (o.getClass() != DefaultWorkItem.class) { + throw new ClassCastException(o.getClass().getName()); + } else { + return ((DefaultWorkItem) o).getId().compareTo(getId()); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java new file mode 100644 index 0000000000..1a7639b41d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import java.rmi.server.UID; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Property; + +import commonj.work.Work; +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkItem; +import commonj.work.WorkListener; +import commonj.work.WorkManager; +import commonj.work.WorkRejectedException; + +/** + * A thread-pool based implementation for the JSR-237 work manager. + *

      + *

      + * 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(@Property(name = "poolSize") int threadPoolSize) { + executor = Executors.newFixedThreadPool(threadPoolSize); + } + + /** + * Schedules a unit of work asynchronously. + * + * @param work Work that needs to be scheduled. + * @return Work Work item representing the asynchronous work + */ + public WorkItem schedule(Work work) throws WorkException { + return schedule(work, null); + } + + /** + * Schedules a unit of work asynchronously. + * + * @param work Work that needs to be scheduled. + * @param workListener Work listener for callbacks. + * @return Work Work item representing the asynchronous work + */ + public WorkItem schedule(Work work, WorkListener workListener) throws WorkRejectedException { + + DefaultWorkItem workItem = new DefaultWorkItem(new UID().toString(), work); + if (workListener != null) { + workItems.put(workItem, workListener); + } + workAccepted(workItem, work); + if (scheduleWork(work, workItem)) { + return workItem; + } else { + workItem.setStatus(WorkEvent.WORK_REJECTED); + if (workListener != null) { + workListener.workRejected(new DefaultWorkEvent(workItem)); + } + throw new WorkRejectedException("Unable to schedule work"); + } + } + + /** + * Wait for all the specified units of work to finish. + * + * @param works Units of the work that need to finish. + * @param timeout Timeout for waiting for the units of work to finish. + */ + public boolean waitForAll(Collection works, long timeout) { + throw new UnsupportedOperationException("waitForAll not supported"); + } + + /** + * Wait for any of the specified units of work to finish. + * + * @param works Units of the work that need to finish. + * @param timeout Timeout for waiting for the units of work to finish. + */ + public Collection waitForAny(Collection works, long timeout) { + throw new UnsupportedOperationException("waitForAny not supported"); + } + + /** + * Method provided for subclasses to indicate a work accptance. + * + * @param workItem Work item representing the work that was accepted. + * @param work Work that was accepted. + */ + private void workAccepted(final DefaultWorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_ACCEPTED); + WorkEvent event = new DefaultWorkEvent(workItem); + listener.workAccepted(event); + } + } + + /* + * Method to indicate a work start. + */ + private void workStarted(final DefaultWorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_STARTED); + WorkEvent event = new DefaultWorkEvent(workItem); + listener.workStarted(event); + } + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final DefaultWorkItem workItem, final Work work) { + workCompleted(workItem, work, null); + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final DefaultWorkItem workItem, final Work work, final WorkException exception) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_COMPLETED); + workItem.setResult(work); + workItem.setException(exception); + WorkEvent event = new DefaultWorkEvent(workItem); + listener.workCompleted(event); + workItems.remove(workItem); + } + } + + /* + * Schedules the work using the threadpool. + */ + private boolean scheduleWork(final Work work, final DefaultWorkItem workItem) { + try { + executor.execute(new DecoratingWork(workItem, work)); + return true; + } catch (RejectedExecutionException ex) { + return false; + } + } + + /* + * Class that decorates the original worker so that it can get callbacks when work is done. + */ + private final class DecoratingWork implements Runnable { + + // Work item for this work. + private DefaultWorkItem workItem; + + // The original work. + private Work decoratedWork; + + /* + * Initializes the work item and underlying work. + */ + private DecoratingWork(final DefaultWorkItem workItem, final Work decoratedWork) { + this.workItem = workItem; + this.decoratedWork = decoratedWork; + } + + /* + * Overrides the run method. + */ + public void run() { + workStarted(workItem, decoratedWork); + try { + decoratedWork.run(); + workCompleted(workItem, decoratedWork); + } catch (Throwable th) { + workCompleted(workItem, decoratedWork, new WorkException(th.getMessage(), th)); + } + } + + } + + @Destroy + public void destroy() { + executor.shutdown(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/test/SCATestCaseRunner.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/test/SCATestCaseRunner.java new file mode 100644 index 0000000000..191dacdf0d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/test/SCATestCaseRunner.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.core.test; + +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$ $Date$ + */ +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 = (URLClassLoader)testClass.getClassLoader(); + if (classLoader instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader)classLoader).getURLs(); + classLoader = new URLClassLoader(urls, classLoader.getParent()); + } else { + classLoader = new URLClassLoader(new URL[0], classLoader); + } + + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + + testCaseClass = Class.forName(testClass.getName(), true, classLoader); + testCase = testCaseClass.newInstance(); + + junit3TestCaseClass = Class.forName("junit.framework.TestCase", true, classLoader); + + testSuiteClass = Class.forName("junit.framework.TestSuite", true, classLoader); + Constructor testSuiteConstructor = testSuiteClass.getConstructor(Class.class); + testSuite = testSuiteConstructor.newInstance(testCaseClass); + + testResultClass = Class.forName("junit.framework.TestResult", true, classLoader); + + try { + beforeAnnotation = Class.forName("org.junit.Before", true, classLoader); + afterAnnotation = Class.forName("org.junit.After", true, classLoader); + beforeClassAnnotation = Class.forName("org.junit.BeforeClass", true, classLoader); + afterClassAnnotation = Class.forName("org.junit.AfterClass", true, classLoader); + junit4AdapterClass = Class.forName("junit.framework.JUnit4TestAdapter", true, classLoader); + } 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/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java new file mode 100644 index 0000000000..a8c57db9d1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.util; + +import java.io.File; +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLClassLoader; + +/** + * Functions to create & manipulate classloaders. + * + * @version $$Rev$$ $$Date$$ + */ + +public final class ClassLoaderHelper { + /** + * Hide constructor + */ + private ClassLoaderHelper() { + } + + /** + * Create a classloader for the supplied classpath. + * + * @param path a list of file/directory names separated by the platform path separator + * @param parent the parent for the new classloader + * @return a classloader that will load classes from the supplied path + */ + public static ClassLoader createClassLoader(ClassLoader parent, String path) { + String[] files = path.split(File.pathSeparator); + return createClassLoader(parent, files); + } + + /** + * Create a classloader for a classpath supplied as individual file names. + * + * @param files a list of file/directory names + * @param parent the parent for the new classloader + * @return a classloader that will load classes from the supplied path + */ + public static ClassLoader createClassLoader(ClassLoader parent, String[] files) { + URL[] urls = new URL[files.length]; + for (int i = 0; i < files.length; i++) { + try { + File file = new File(files[i]); + urls[i] = file.toURI().toURL(); + } catch (MalformedURLException e) { + // just ignore this value + continue; + } + } + + return new URLClassLoader(urls, parent); + } + + /** + * Create a classloader for a classpath supplied as a list of files. + * + * @param files a list of files + * @param parent the parent for the new classloader + * @return a classloader that will load classes from the supplied path + */ + public static ClassLoader createClassLoader(ClassLoader parent, File[] files) { + URL[] urls = new URL[files.length]; + for (int i = 0; i < files.length; i++) { + try { + File file = files[i]; + urls[i] = file.toURI().toURL(); + } catch (MalformedURLException e) { + + continue; + } + } + return new URLClassLoader(urls, parent); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java new file mode 100644 index 0000000000..2544c90846 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/FileHelper.java @@ -0,0 +1,704 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.util; + +import java.io.File; +import java.io.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 = '\\'; + + protected FileHelper() { + } + + /** + * 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()) { + 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/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java new file mode 100644 index 0000000000..e3f0ebb5c4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/IOHelper.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.util.jar.JarFile; + +public class IOHelper { + /** + * The default buffer size to use. + */ + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + protected IOHelper() { + + } + + /** + * 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$ $Date$ + */ + 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 { + is = url.openStream(); + } + } + + public SafeURLInputStream(JarURLConnection connection) throws IOException { + // We cannot use cache + connection.setUseCaches(false); + is = connection.getInputStream(); + jarFile = connection.getJarFile(); + } + + public int available() throws IOException { + return is.available(); + } + + public void close() throws IOException { + is.close(); + // We need to close the JAR file + if (jarFile != null) { + jarFile.close(); + } + } + + public synchronized void mark(int readlimit) { + is.mark(readlimit); + } + + public boolean markSupported() { + return is.markSupported(); + } + + public int read() throws IOException { + return is.read(); + } + + public int read(byte[] b, int off, int len) throws IOException { + return is.read(b, off, len); + } + + public int read(byte[] b) throws IOException { + return is.read(b); + } + + public synchronized void reset() throws IOException { + is.reset(); + } + + public long skip(long n) throws IOException { + return is.skip(n); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java new file mode 100644 index 0000000000..6b11725481 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java @@ -0,0 +1,439 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Implements various reflection-related operations + * + * @version $Rev$ $Date$ + */ +public final class JavaIntrospectionHelper { + + private static final Class[] EMPTY_CLASS_ARRY = new Class[0]; + + /** + * Hide the constructor + */ + private JavaIntrospectionHelper() { + } + + + /** + * Returns a collection of public, and protected fields declared by a class or one of its supertypes + */ + public static Set getAllPublicAndProtectedFields(Class clazz) { + return getAllPublicAndProtectedFields(clazz, new HashSet()); + } + + /** + * Recursively evaluates the type hierachy to return all fields that are public or protected + */ + private static Set getAllPublicAndProtectedFields(Class clazz, Set fields) { + if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) { + return fields; + } + fields = getAllPublicAndProtectedFields(clazz.getSuperclass(), fields); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { + int modifiers = field.getModifiers(); + if ((Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) && !Modifier.isStatic(modifiers)) { + field.setAccessible(true); // ignore Java accessibility + fields.add(field); + } + } + return fields; + } + + /** + * Returns a collection of public and protected methods declared by a class or one of its supertypes. Note that + * overriden methods will not be returned in the collection (i.e. only the method override will be).

      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) { + return getAllUniqueMethods(clazz, new HashSet()); + } + + /** + * Recursively evaluates the type hierarchy to return all unique methods + */ + private static Set getAllUniqueMethods(Class pClass, Set methods) { + if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) { + return methods; + } + // we first evaluate methods of the subclass and then move to the parent + Method[] declaredMethods = pClass.getDeclaredMethods(); + for (Method declaredMethod : declaredMethods) { + int modifiers = declaredMethod.getModifiers(); + if ((!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers)) || Modifier.isStatic(modifiers)) { + continue; + } + if (methods.size() == 0) { + methods.add(declaredMethod); + } else { + List temp = new ArrayList(); + boolean matched = false; + for (Method method : methods) { + // only add if not already in the set from a supclass (i.e. the + // method is not overrided) + if (exactMethodMatch(declaredMethod, method)) { + matched = true; + break; + } + } + if (!matched) { + // TODO ignore Java accessibility + declaredMethod.setAccessible(true); + temp.add(declaredMethod); + } + methods.addAll(temp); + temp.clear(); + } + } + // evaluate class hierarchy - this is done last to track inherited methods + methods = getAllUniqueMethods(pClass.getSuperclass(), methods); + return methods; + } + + /** + * Finds the closest matching field with the given name, that is, a field of the exact specified type or, + * alternately, of a supertype. + * + * @param name the name of the field + * @param type the field type + * @param fields the collection of fields to search + * @return the matching field or null if not found + */ + public static Field findClosestMatchingField(String name, Class type, Set 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; + } + } + + /** + * Searches a collection of fields for one that matches by name and has a multiplicity type. i.e. a List or Array of + * interfaces + * + * @return a matching field or null + */ + public static Field findMultiplicityFieldByName(String name, Set fields) { + for (Field candidate : fields) { + if (candidate.getName().equals(name) + && (List.class.isAssignableFrom(candidate.getType()) || (candidate.getType().isArray() + && candidate.getType().getComponentType() != null && candidate.getType().getComponentType() + .isInterface()))) { + return candidate; + } + } + return null; + } + + /** + * Searches a collection of method for one that matches by name and has single parameter of a multiplicity type. + * i.e. a List or Array of interfaces + * + * @return a matching method or null + */ + public static Method findMultiplicityMethodByName(String name, Set methods) { + for (Method candidate : methods) { + if (candidate.getName().equals(name) + && candidate.getParameterTypes().length == 1 + && (List.class.isAssignableFrom(candidate.getParameterTypes()[0]) + || (candidate.getParameterTypes()[0].isArray() + && candidate.getParameterTypes()[0].getComponentType() != null + && candidate.getParameterTypes()[0].getComponentType().isInterface()))) { + return candidate; + } + } + return null; + } + + /** + * Determines if two methods "match" - that is, they have the same method names and exact parameter types (one is + * not a supertype of the other) + */ + public static boolean exactMethodMatch(Method method1, Method method2) { + if (!method1.getName().equals(method2.getName())) { + return false; + } + Class[] types1 = method1.getParameterTypes(); + Class[] types2 = method2.getParameterTypes(); + if (types1.length == 0 && types2.length == 0) { + return true; + } else if (types1.length == types2.length) { + for (int n = 0; n < types1.length; n++) { + if (!types1[n].equals(types2[n])) { + return false; + } + } + return true; + } + return false; + } + + public static Constructor getDefaultConstructor(Class clazz) throws NoSuchMethodException { + return clazz.getConstructor((Class[]) null); + } + + /** + * Loads a class corresponding to the class name using the current context class loader. + * + * @throws ClassNotFoundException if the class was not found on the classpath + */ + public static Class loadClass(String pName) throws ClassNotFoundException { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + return Class.forName(pName, true, loader); + } + + /** + * Returns the simple name of a class - i.e. the class name devoid of its package qualifier + * + * @param implClass the implmentation class + */ + public static String getBaseName(Class implClass) { + String baseName = implClass.getName(); + int lastDot = baseName.lastIndexOf('.'); + if (lastDot != -1) { + baseName = baseName.substring(lastDot + 1); + } + return baseName; + } + + public static boolean isImmutable(Class clazz) { + return String.class == clazz + || clazz.isPrimitive() + || Number.class.isAssignableFrom(clazz) + || Boolean.class.isAssignableFrom(clazz) + || Character.class.isAssignableFrom(clazz) + || Byte.class.isAssignableFrom(clazz); + } + + /** + * Takes a property name and converts it to a getter method name according to JavaBean conventions. For example, + * property 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; + } + return Character.toLowerCase(name.charAt(3)) + name.substring(4); + } + + /** + * Takes a property name and converts it to a setter method name according to JavaBean conventions. For example, the + * property 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); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ReferenceLoaderHelper.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ReferenceLoaderHelper.java new file mode 100644 index 0000000000..dad586dd18 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ReferenceLoaderHelper.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.util; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.tuscany.spi.loader.IncompatibleOverridingServiceContractException; +import org.apache.tuscany.spi.loader.InvalidReferenceException; +import org.apache.tuscany.spi.model.CompositeReferenceDefinition; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceContract; + +/** + * Functions to help in loading of references + */ + +public final class ReferenceLoaderHelper { + /** + * Hide constructor + */ + private ReferenceLoaderHelper() { + } + + public static void populateRefTargets(AbstractReferenceDefinition refDefn, String concatenatedTargets) throws InvalidReferenceException { + StringTokenizer st = new StringTokenizer(concatenatedTargets); + while (st.hasMoreTokens()) { + try { + refDefn.addTarget(new URI(st.nextToken())); + } catch (URISyntaxException e) { + throw new InvalidReferenceException(e); + } + } + } + + public static void populatePromotedRefs(CompositeReferenceDefinition refDefn, String concatenatedUris) throws InvalidReferenceException { + StringTokenizer st = new StringTokenizer(concatenatedUris); + while (st.hasMoreTokens()) { + try { + refDefn.addPromotedReference(new URI(st.nextToken())); + } catch (URISyntaxException e) { + throw new InvalidReferenceException(e); + } + } + } + + public static boolean isCompatibleMultiplicity(Multiplicity definedMul, Multiplicity overridenMul) { + return ((definedMul == overridenMul) || + (definedMul == Multiplicity.ZERO_ONE && overridenMul == Multiplicity.ZERO_N) || + (definedMul == Multiplicity.ZERO_N && overridenMul == Multiplicity.ZERO_ONE) || + (definedMul == Multiplicity.ONE_ONE && overridenMul == Multiplicity.ONE_N) || + (definedMul == Multiplicity.ONE_N && overridenMul == Multiplicity.ONE_ONE)); + } + + public 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; + } + } + + public static boolean validateMultiplicityAndTargets(Multiplicity multiplicity, + List targets) { + int count = targets.size(); + switch (multiplicity) { + case ZERO_N: + break; + case ZERO_ONE: + if (count > 1) { + return false; + } + break; + case ONE_ONE: + if (count != 1) { + return false; + } + break; + case ONE_N: + if (count < 1) { + return false; + } + break; + } + return true; + } + + public static void checkInterfaceCompatibility(ServiceContract source, + ServiceContract target, + boolean ignoreCallback) throws IncompatibleOverridingServiceContractException { + if (source == target) { + // Shortcut for performance + return; + } + + //FIXME: we don't go into operations comparison for now since the service contract thta the + //interace loader loads does not have operation details as the intropection 'has not been deep' + //The JavaInterfaceLoader has set the 'deep' introspection to false....will fix this after + //sorting that out. + + if (source.getInteractionScope() != target.getInteractionScope()) { + throw new IncompatibleOverridingServiceContractException( + "Interaction scopes settings do not match", + source, target); + } + + for (Operation operation : source.getOperations().values()) { + Operation targetOperation = target.getOperation(operation.getName()); + if (targetOperation == null) { + throw new IncompatibleOverridingServiceContractException("Operation not found on target", + source, target); + } + if (!targetOperation.equals(operation)) { + throw new IncompatibleOverridingServiceContractException( + "Target operations are not compatible", + source, target); + } + } + + if (ignoreCallback) { + return; + } + + for (Operation operation : source.getCallbackOperations().values()) { + Operation targetOperation = target.getCallbackOperations().get(operation.getName()); + if (targetOperation == null) { + throw new IncompatibleOverridingServiceContractException( + "Callback operation not found on target", + source, target, null, + targetOperation); + } + if (!operation.equals(targetOperation)) { + throw new IncompatibleOverridingServiceContractException( + "Target callback operation is not compatible", + source, target, operation, + targetOperation); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java new file mode 100644 index 0000000000..c1766fbb6f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; + +/** + * Responsible for bridging an outbound to an inbound invocation chain associated with a source and target respectively + * + * @version $Rev$ $Date$ + */ +public interface BridgingInterceptor extends Interceptor { +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java new file mode 100644 index 0000000000..06f0e62f70 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/CallbackInterfaceInterceptor.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.osoa.sca.NoRegisteredCallbackException; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; + +/** + * An interceptor applied to the outbound side of a wire that ensures the callback target implements the required + * service contract. This is required as callback targets may be set dynamically by service implementations. + * + * @version $Rev$ $Date$ + */ +public class CallbackInterfaceInterceptor implements Interceptor { + private boolean invokingServiceImplements; + private Interceptor next; + + public CallbackInterfaceInterceptor(boolean invokingServiceImplements) { + this.invokingServiceImplements = invokingServiceImplements; + } + + public Message invoke(Message msg) { + // TODO check in the context if a callback object is set, if so invoke next since the setCallback will + // perform the check + if (!invokingServiceImplements) { + throw new NoRegisteredCallbackException("Callback target does not implement the callback interface"); + } + return next.invoke(msg); + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public Interceptor getNext() { + return next; + } + + public boolean isOptimizable() { + return false; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java new file mode 100644 index 0000000000..45b580d419 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; + +/** + * Contains a target-side invocation chain + * + * @version $Rev$ $Date$ + */ +public class InboundInvocationChainImpl extends InvocationChainImpl implements InboundInvocationChain { + + /** + * Creates an new target-side chain for the given operation + */ + public InboundInvocationChainImpl(Operation operation) { + super(operation); + } + + public void prepare() { + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java new file mode 100644 index 0000000000..b529cafbb6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Default implementation of an inbound wire + * + * @version $Rev$ $Date$ + */ +public class InboundWireImpl implements InboundWire { + private QName bindingType = LOCAL_BINDING; + private String serviceName; + private ServiceContract serviceContract; + private OutboundWire targetWire; + private String callbackReferenceName; + private Map, InboundInvocationChain> chains = new HashMap, InboundInvocationChain>(); + private Map, OutboundInvocationChain>> callbackSourceChainMaps = + new HashMap, OutboundInvocationChain>>(); + private SCAObject container; + private AtomicComponent targetComponent; + private boolean optimizable; + + + /** + * Creates a local inbound wire + */ + public InboundWireImpl() { + } + + + /** + * Creates an inbound wire for the given binding type + * + * @param bindingType the binding type + */ + public InboundWireImpl(QName bindingType) { + this.bindingType = bindingType; + } + + public QName getBindingType() { + return bindingType; + } + + public Object getTargetService() throws TargetResolutionException { + // JFM fixme hack + if (targetWire == null && targetComponent != null) { + return targetComponent.getTargetInstance(); + } + assert targetWire != null; + // optimized, no interceptors or handlers on either end + return targetWire.getTargetService(); + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException("Additional proxy interfaces not yet supported"); + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public Map, InboundInvocationChain> getInvocationChains() { + return chains; + } + + public void addInvocationChains(Map, InboundInvocationChain> chains) { + this.chains.putAll(chains); + } + + public void addInvocationChain(Operation operation, InboundInvocationChain chain) { + chains.put(operation, chain); + } + + public Map, OutboundInvocationChain> getSourceCallbackInvocationChains(Object targetAddr) { + return callbackSourceChainMaps.get(targetAddr); + } + + public void addSourceCallbackInvocationChains(Object targetAddr, + Map, OutboundInvocationChain> chains) { + callbackSourceChainMaps.put(targetAddr, chains); + } + + public void addSourceCallbackInvocationChain(Object targetAddr, + Operation operation, + OutboundInvocationChain chain) { + Map, OutboundInvocationChain> chains = callbackSourceChainMaps.get(targetAddr); + if (chains == null) { + chains = new HashMap, OutboundInvocationChain>(); + callbackSourceChainMaps.put(targetAddr, chains); + } + chains.put(operation, chain); + } + + public void setTargetWire(OutboundWire wire) { + targetWire = wire; + } + + public String getCallbackReferenceName() { + return callbackReferenceName; + } + + public void setCallbackReferenceName(String callbackReferenceName) { + this.callbackReferenceName = callbackReferenceName; + } + + public boolean isOptimizable() { + return optimizable; + } + + public void setOptimizable(boolean optimizable) { + this.optimizable = optimizable; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + if (container instanceof AtomicComponent) { + targetComponent = (AtomicComponent) container; + } + this.container = container; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java new file mode 100644 index 0000000000..92da622d11 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/IncompatibleServiceContractExceptionFormatter.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.io.PrintWriter; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.IncompatibleServiceContractException; + +import org.apache.tuscany.host.monitor.ExceptionFormatter; +import org.apache.tuscany.host.monitor.FormatterRegistry; + +/** + * Formats {@link org.apache.tuscany.spi.wire.IncompatibleServiceContractException} for JDK logging + * + * @version $Rev$ $Date$ + */ +@EagerInit +public class IncompatibleServiceContractExceptionFormatter implements ExceptionFormatter { + private FormatterRegistry factory; + + public IncompatibleServiceContractExceptionFormatter(@Autowire FormatterRegistry factory) { + this.factory = factory; + factory.register(this); + } + + public boolean canFormat(Class type) { + return IncompatibleServiceContractException.class.isAssignableFrom(type); + } + + @Destroy + public void destroy() { + factory.unregister(this); + } + + public PrintWriter write(PrintWriter writer, Throwable exception) { + assert exception instanceof IncompatibleServiceContractException; + IncompatibleServiceContractException e = (IncompatibleServiceContractException) exception; + e.appendBaseMessage(writer); + ServiceContract source = e.getSource(); + String sourceContractName = null; + if (source != null) { + sourceContractName = source.getInterfaceName(); + } + Operation sourceOperation = e.getSourceOperation(); + String sourceOpName = null; + if (sourceOperation != null) { + sourceOpName = sourceOperation.getName(); + } + if (sourceOpName == null) { + writer.write("\nSource Contract: " + sourceContractName); + } else { + writer.write("\nSource Contract: " + sourceContractName + "/" + sourceOpName); + } + ServiceContract target = e.getTarget(); + String targetContractName = null; + if (target != null) { + targetContractName = target.getInterfaceName(); + } + Operation targetOperation = e.getTargetOperation(); + String targetOpName = null; + if (targetOperation != null) { + targetOpName = targetOperation.getName(); + } + if (targetOpName == null) { + writer.write("\nTarget Contract: " + targetContractName + "\n"); + } else { + writer.write("\nTarget Contract: " + targetContractName + "/" + targetOpName + "\n"); + + } + e.appendContextStack(writer); + return writer; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java new file mode 100644 index 0000000000..d93426af4c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Contains functionality common to source- and target- side invocation chains + * + * @version $Rev$ $Date$ + */ +public abstract class InvocationChainImpl implements InvocationChain { + protected Operation operation; + protected TargetInvoker targetInvoker; + protected Interceptor interceptorChainHead; + protected Interceptor interceptorChainTail; + + + // the pointer to a bridged target head interceptor or null if the target has no interceptors + protected Interceptor targetInterceptorChainHead; + + public InvocationChainImpl(Operation operation) { + assert operation != null : "No operation type specified"; + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } + + public void setTargetInvoker(TargetInvoker invoker) { + this.targetInvoker = invoker; + } + + public TargetInvoker getTargetInvoker() { + return targetInvoker; + } + + public void addInterceptor(Interceptor interceptor) { + if (interceptorChainHead == null) { + interceptorChainHead = interceptor; + } else { + interceptorChainTail.setNext(interceptor); + } + interceptorChainTail = interceptor; + } + + public void addInterceptor(int index, Interceptor interceptor) { + int i = 0; + Interceptor next = interceptorChainHead; + Interceptor prev = null; + while (next != null && i < index) { + prev = next; + next = next.getNext(); + i++; + } + if (i == index) { + if (prev != null) { + prev.setNext(interceptor); + } else { + interceptorChainHead = interceptor; + } + interceptor.setNext(next); + if (next == null) { + interceptorChainTail = interceptor; + } + } else { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + public Interceptor getHeadInterceptor() { + return interceptorChainHead; + } + + public Interceptor getTailInterceptor() { + return interceptorChainTail; + } + + public void setTargetInterceptor(Interceptor interceptor) { + targetInterceptorChainHead = interceptor; + } + + public Interceptor getTargetInterceptor() { + return targetInterceptorChainHead; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java new file mode 100644 index 0000000000..90b17a930c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Serves as a tail interceptor on a target wire chain. This implementation dispatches to the target invoker passed + * inside the wire message. Target invokers are passed from the source in order to allow for caching of target + * instances. + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.spi.wire.TargetInvoker + */ +public class InvokerInterceptor implements Interceptor { + + public InvokerInterceptor() { + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + TargetInvoker invoker = msg.getTargetInvoker(); + if (invoker == null) { + throw new InvocationRuntimeException("No target invoker specified on message"); + } + return invoker.invoke(msg); + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last one in an target interceptor chain"); + } + + public Interceptor getNext() { + return null; + } + + public boolean isOptimizable() { + return true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java new file mode 100644 index 0000000000..a2cd71cafe --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/LoopBackWire.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.component.TargetResolutionException; + +/** + * A specialized wire that points back to its target container. Used to autowire to parent composites + * + * @version $Rev$ $Date$ + */ +public class LoopBackWire extends InboundWireImpl { + + public Object getTargetService() throws TargetResolutionException { + return getContainer(); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java new file mode 100644 index 0000000000..aec281d190 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NoMethodForOperationException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.ProxyCreationException; + +/** + * Thrown when an {@link org.apache.tuscany.spi.model.Operation} cannot be mapped to a method on an interface + * @version $Rev$ $Date$ + */ +public class NoMethodForOperationException extends ProxyCreationException { + public NoMethodForOperationException() { + } + + public NoMethodForOperationException(String message) { + super(message); + } + + public NoMethodForOperationException(String message, Throwable cause) { + super(message, cause); + } + + public NoMethodForOperationException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java new file mode 100644 index 0000000000..a2e6b0379f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.util.LinkedList; + +import org.osoa.sca.ServiceRuntimeException; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.model.Scope; + +/** + * Bridges interceptors in a non-blocking fashion between an {@link org.apache.tuscany.spi.wire.InboundInvocationChain} + * and an {@link org.apache.tuscany.spi.wire.OutboundInvocationChain} by using a {@link + * org.apache.tuscany.spi.component.WorkContext}. + * + * @version $$Rev$$ $$Date$$ + */ +public class NonBlockingBridgingInterceptor implements BridgingInterceptor { + + private static final Message RESPONSE = new ImmutableMessage(); + + private WorkScheduler workScheduler; + private WorkContext workContext; + private Interceptor next; + + public NonBlockingBridgingInterceptor(WorkScheduler workScheduler, WorkContext workContext) { + this.workScheduler = workScheduler; + this.workContext = workContext; + } + + public NonBlockingBridgingInterceptor(WorkScheduler workScheduler, WorkContext workContext, Interceptor next) { + this.workScheduler = workScheduler; + this.workContext = workContext; + this.next = next; + } + + public Message invoke(final Message msg) { + // Retrieve conversation id to transfer to new thread + // Notice that we cannot clear the conversation id from the current thread + final Object conversationID = workContext.getIdentifier(Scope.CONVERSATION); + // Schedule the invocation of the next interceptor in a new Work instance + try { + workScheduler.scheduleWork(new Runnable() { + public void run() { + workContext.setCurrentCorrelationId(null); + // if we got a conversation id, transfer it to new thread + if (conversationID != null) { + workContext.setIdentifier(Scope.CONVERSATION, conversationID); + } + next.invoke(msg); + } + }); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + return RESPONSE; + } + + public Interceptor getNext() { + return next; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public boolean isOptimizable() { + return false; + } + + /** + * A dummy message passed back on an invocation + */ + private static class ImmutableMessage implements Message { + + public Object getBody() { + return null; + } + + public void setBody(Object body) { + if (body != null) { + throw new UnsupportedOperationException(); + } + } + + public void setTargetInvoker(TargetInvoker invoker) { + throw new UnsupportedOperationException(); + } + + public TargetInvoker getTargetInvoker() { + return null; + } + + public Message getRelatedCallbackMessage() { + return null; + } + + public Object getFromAddress() { + return null; + } + + public void setFromAddress(Object fromAddress) { + throw new UnsupportedOperationException(); + } + + public Object popFromAddress() { + return null; + } + + public void pushFromAddress(Object fromAddress) { + throw new UnsupportedOperationException(); + } + + public LinkedList getCallbackRoutingChain() { + return null; + } + + public void setCallbackRoutingChain(LinkedList fromAddresses) { + throw new UnsupportedOperationException(); + } + + public Object getMessageId() { + return null; + } + + public void setMessageId(Object messageId) { + throw new UnsupportedOperationException(); + } + + public Object getCorrelationId() { + return null; + } + + public void setCorrelationId(Object correlationId) { + throw new UnsupportedOperationException(); + } + + public boolean isFault() { + return false; + } + + public void setBodyWithFault(Object fault) { + throw new UnsupportedOperationException(); + } + + public short getConversationSequence() { + return TargetInvoker.NONE; + } + + public void setConversationSequence(short sequence) { + + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java new file mode 100644 index 0000000000..4a4b268201 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OptimizedWireObjectFactory.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Returns a target instance directly from a wire + * + * @version $Rev$ $Date$ + */ +public class OptimizedWireObjectFactory implements ObjectFactory { + + private OutboundWire wire; + + public OptimizedWireObjectFactory(OutboundWire factory) { + this.wire = factory; + } + + public Object getInstance() throws ObjectCreationException { + try { + return wire.getTargetService(); + } catch (TargetResolutionException e) { + throw new ObjectCreationException(e); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java new file mode 100644 index 0000000000..a9d83cb7a0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +/** + * Contains a outgoing invocation pipeline for a service operation. + * + * @version $Rev$ $Date$ + */ +public class OutboundInvocationChainImpl extends InvocationChainImpl implements OutboundInvocationChain { + + /** + * Creates an new outbound chain + */ + public OutboundInvocationChainImpl(Operation operation) { + super(operation); + } + + public void prepare() { + if (interceptorChainHead != null) { + if (targetInterceptorChainHead != null) { + // Connect source interceptor chain directly to target interceptor chain + interceptorChainTail.setNext(targetInterceptorChainHead); + } + } else { + // no source interceptor chain or source handlers, connect to target interceptor chain or channel + if (targetInterceptorChainHead != null) { + interceptorChainHead = targetInterceptorChainHead; + interceptorChainTail = targetInterceptorChainHead; + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java new file mode 100644 index 0000000000..bad92ffe1e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Default implementation of an outbound wire + * + * @version $Rev$ $Date$ + */ +public class OutboundWireImpl implements OutboundWire { + private QName bindingType = LOCAL_BINDING; + private ServiceContract serviceContract; + private Class[] callbackInterfaces; + private Map, OutboundInvocationChain> chains = new HashMap, OutboundInvocationChain>(); + private Map, InboundInvocationChain> callbackTargetChains = + new HashMap, InboundInvocationChain>(); + private String referenceName; + private QualifiedName targetName; + private InboundWire targetWire; + private SCAObject container; + private boolean autowire; + private boolean optimizable; + + /** + * Creates a local outbound wire + */ + public OutboundWireImpl() { + } + + /** + * Creates an outbound wire for the given binding type + * + * @param bindingType the binding type + */ + public OutboundWireImpl(QName bindingType) { + this.bindingType = bindingType; + } + + public void setOptimizable(boolean optimizable) { + this.optimizable = optimizable; + } + + public QName getBindingType() { + return bindingType; + } + + public Object getTargetService() throws TargetResolutionException { + if (targetWire == null) { + return null; + } + // optimized, no interceptors or handlers on either end + return targetWire.getTargetService(); + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException("Additional proxy interfaces not yet supported"); + } + + public void setCallbackInterface(Class interfaze) { + callbackInterfaces = new Class[]{interfaze}; + } + + public Class getCallbackInterface() { + return callbackInterfaces[0]; + } + + public void addCallbackInterface(Class claz) { + throw new UnsupportedOperationException("Additional callback interfaces not yet supported"); + } + + public Class[] getImplementedCallbackInterfaces() { + return callbackInterfaces; + } + + public void setTargetWire(InboundWire wire) { + this.targetWire = wire; + } + + public Map, OutboundInvocationChain> getInvocationChains() { + return chains; + } + + public void addInvocationChains(Map, OutboundInvocationChain> chains) { + this.chains.putAll(chains); + } + + public void addInvocationChain(Operation operation, OutboundInvocationChain chain) { + chains.put(operation, chain); + } + + public Map, InboundInvocationChain> getTargetCallbackInvocationChains() { + return callbackTargetChains; + } + + public void addTargetCallbackInvocationChains(Map, InboundInvocationChain> chains) { + callbackTargetChains.putAll(chains); + } + + public void addTargetCallbackInvocationChain(Operation operation, InboundInvocationChain chain) { + callbackTargetChains.put(operation, chain); + } + + public String getReferenceName() { + return referenceName; + } + + public void setReferenceName(String referenceName) { + this.referenceName = referenceName; + } + + public QualifiedName getTargetName() { + return targetName; + } + + public void setTargetName(QualifiedName targetName) { + this.targetName = targetName; + } + + public boolean isAutowire() { + return autowire; + } + + public void setAutowire(boolean autowire) { + this.autowire = autowire; + } + + public boolean isOptimizable() { + return optimizable; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + this.container = container; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java new file mode 100644 index 0000000000..f09bda400a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; + +/** + * Synchronously bridges interceptors between an {@link org.apache.tuscany.spi.wire.InboundInvocationChain} and an + * {@link org.apache.tuscany.spi.wire.OutboundInvocationChain}. + * + * @version $$Rev$$ $$Date$$ + */ +public class SynchronousBridgingInterceptor implements BridgingInterceptor { + private Interceptor next; + + public SynchronousBridgingInterceptor() { + } + + public SynchronousBridgingInterceptor(Interceptor next) { + this.next = next; + } + + public Message invoke(Message msg) { + return next.invoke(msg); + } + + public Interceptor getNext() { + return next; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public boolean isOptimizable() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java new file mode 100644 index 0000000000..c04869e8f5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireObjectFactory.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.TargetResolutionException; +import org.apache.tuscany.spi.wire.OutboundChainHolder; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WireService; + +/** + * Uses a wire to return an object instance + * + * @version $Rev$ $Date$ + */ +public class WireObjectFactory implements ObjectFactory { + private Class interfaze; + private OutboundWire wire; + private WireService wireService; + // the cache of proxy interface method to operation mappings + private Map mappings; + private boolean optimizable; + + /** + * Constructor. + * + * @param interfaze the interface to inject on the client + * @param wire the backing wire + * @param wireService the wire service to create the proxy + * @throws NoMethodForOperationException + */ + public WireObjectFactory(Class interfaze, OutboundWire wire, WireService wireService) + throws NoMethodForOperationException { + this.interfaze = interfaze; + this.wire = wire; + this.wireService = wireService; + this.mappings = WireUtils.createInterfaceToWireMapping(interfaze, wire); + } + + public T getInstance() throws ObjectCreationException { + // note optimization must be done lazily as wire object factories are created during the build phase prior + // to the outbound and inbound wires being connected + if ((optimizable + || wire.isOptimizable()) + && wire.getServiceContract().getInterfaceClass() != null + && interfaze.isAssignableFrom(wire.getServiceContract().getInterfaceClass())) { + optimizable = true; + try { + return interfaze.cast(wire.getTargetService()); + } catch (TargetResolutionException e) { + throw new ObjectCreationException(e); + } + } + // clone the cached mappings + Map newChains = new HashMap(mappings.size()); + for (Map.Entry entry : mappings.entrySet()) { + newChains.put(entry.getKey(), entry.getValue().clone()); + } + return interfaze.cast(wireService.createProxy(interfaze, wire, newChains)); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java new file mode 100644 index 0000000000..80ab5b361a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireServiceExtension.java @@ -0,0 +1,323 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.core.binding.local.LocalReferenceBinding; +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ReferenceBinding; +import org.apache.tuscany.spi.component.ServiceBinding; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentReferenceDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ComponentTypeReferenceDefinition; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.AbstractReferenceDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.policy.PolicyBuilderRegistry; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.IncompatibleServiceContractException; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WireService; + +/** + * Base class for wire service extensions + * + * @version $Rev$ $Date$ + */ +public abstract class WireServiceExtension implements WireService { + protected PolicyBuilderRegistry policyRegistry; + protected WorkContext context; + + protected WireServiceExtension(WorkContext context, PolicyBuilderRegistry policyRegistry) { + this.policyRegistry = policyRegistry; + this.context = context; + } + + public OutboundInvocationChain createOutboundChain(Operation operation) { + return new OutboundInvocationChainImpl(operation); + } + + public InboundInvocationChain createInboundChain(Operation operation) { + return new InboundInvocationChainImpl(operation); + } + + public InboundWire createWire(ServiceDefinition service) { + InboundWire wire = new InboundWireImpl(); + ServiceContract contract = service.getServiceContract(); + wire.setServiceContract(contract); + wire.setServiceName(service.getName()); + for (Operation operation : contract.getOperations().values()) { + InboundInvocationChain chain = createInboundChain(operation); + // TODO handle policy + chain.addInterceptor(new InvokerInterceptor()); + wire.addInvocationChain(operation, chain); + } + if (contract.getCallbackName() != null) { + wire.setCallbackReferenceName(service.getCallbackReferenceName()); + } + return wire; + } + + public void createWires(AtomicComponent component, ComponentDefinition definition) { + Implementation implementation = definition.getImplementation(); + ComponentType componentType = implementation.getComponentType(); + // create incoming service wires + for (ServiceDefinition service : componentType.getServices().values()) { + InboundWire wire = createWire(service); + wire.setContainer(component); + component.addInboundWire(wire); + } + // create outgoing reference wires + for (ComponentReferenceDefinition refDefn : definition.getReferences().values()) { + if (!refDefn.isWiredByImpl()) { + List wires = createWire(refDefn.getTargets(), refDefn); + Multiplicity multiplicity = refDefn.getMultiplicity(); + if (multiplicity == Multiplicity.ZERO_ONE || multiplicity == Multiplicity.ONE_ONE) { + // 0..1 or 1..1 + for (OutboundWire wire : wires) { + wire.setContainer(component); + component.addOutboundWire(wire); + } + } else { + // 0..N or 1..N + for (OutboundWire wire : wires) { + wire.setContainer(component); + } + component.addOutboundWires(wires); + } + } + } + } + + public void createWires(ReferenceBinding referenceBinding, ServiceContract contract, QualifiedName targetName) { + InboundWire inboundWire = new InboundWireImpl(referenceBinding.getBindingType()); + inboundWire.setServiceContract(contract); + inboundWire.setContainer(referenceBinding); + for (Operation operation : contract.getOperations().values()) { + InboundInvocationChain chain = createInboundChain(operation); + inboundWire.addInvocationChain(operation, chain); + } + OutboundWire outboundWire = new OutboundWireImpl(referenceBinding.getBindingType()); + outboundWire.setTargetName(targetName); + + // [rfeng] Check if the Reference has the binding contract + ServiceContract bindingContract = referenceBinding.getBindingServiceContract(); + if (bindingContract == null) { + bindingContract = contract; + } + outboundWire.setServiceContract(bindingContract); + outboundWire.setContainer(referenceBinding); + for (Operation operation : bindingContract.getOperations().values()) { + OutboundInvocationChain chain = createOutboundChain(operation); + if (referenceBinding instanceof LocalReferenceBinding) { + // Not ideal but the local binding case is special as its inbound and outbound wires are connected + // before the outbound wire is connected to the reference target. This requires the binding outbound + // chain to have an interceptor to connect to from the binding inbound chain. This outbound + // interceptor will then be bridged to the head target interceptor + chain.addInterceptor(new SynchronousBridgingInterceptor()); + } else { + chain.addInterceptor(new InvokerInterceptor()); + } + outboundWire.addInvocationChain(operation, chain); + } + // Add target callback chain to outbound wire + if (contract.getCallbackName() != null) { + outboundWire.setCallbackInterface(contract.getCallbackClass()); + for (Operation operation : contract.getCallbackOperations().values()) { + InboundInvocationChain callbackTargetChain = createInboundChain(operation); + // TODO handle policy + callbackTargetChain.addInterceptor(new InvokerInterceptor()); + outboundWire.addTargetCallbackInvocationChain(operation, callbackTargetChain); + } + } + referenceBinding.setInboundWire(inboundWire); + referenceBinding.setOutboundWire(outboundWire); + } + + public void createWires(ServiceBinding serviceBinding, ServiceContract contract, String targetName) { + InboundWire inboundWire = new InboundWireImpl(serviceBinding.getBindingType()); + // [rfeng] Check if the Reference has the serviceBinding contract + ServiceContract bindingContract = serviceBinding.getBindingServiceContract(); + if (bindingContract == null) { + bindingContract = contract; + } + inboundWire.setServiceContract(bindingContract); + inboundWire.setContainer(serviceBinding); + for (Operation operation : bindingContract.getOperations().values()) { + InboundInvocationChain inboundChain = createInboundChain(operation); + inboundChain.addInterceptor(new SynchronousBridgingInterceptor()); + inboundWire.addInvocationChain(operation, inboundChain); + } + + OutboundWire outboundWire = new OutboundWireImpl(serviceBinding.getBindingType()); + outboundWire.setServiceContract(contract); + outboundWire.setTargetName(new QualifiedName(targetName)); + outboundWire.setContainer(serviceBinding); + + for (Operation operation : contract.getOperations().values()) { + OutboundInvocationChain outboundChain = createOutboundChain(operation); + outboundWire.addInvocationChain(operation, outboundChain); + } + + // Add target callback chain to outbound wire + if (contract.getCallbackName() != null) { + outboundWire.setCallbackInterface(contract.getCallbackClass()); + for (Operation operation : contract.getCallbackOperations().values()) { + InboundInvocationChain callbackTargetChain = createInboundChain(operation); + // TODO handle policy + callbackTargetChain.addInterceptor(new InvokerInterceptor()); + outboundWire.addTargetCallbackInvocationChain(operation, callbackTargetChain); + } + } + serviceBinding.setInboundWire(inboundWire); + serviceBinding.setOutboundWire(outboundWire); + } + + /** + * Compares two operations for wiring compatibility as defined by the SCA assembly specification, namely:

        + *
      1. compatibility for the individual method is defined as compatibility of the signature, that is method name, + * input types, and output types MUST BE the same.
      2. the order of the input and output types also MUST BE the + * same.
      3. the set of Faults and Exceptions expected by the source MUST BE the same or be a superset of those + * specified by the service.
      + * + * @param source the source contract to compare + * @param target the target contract to compare + * @throws org.apache.tuscany.spi.wire.IncompatibleServiceContractException + * if the two contracts don't match + */ + public void checkCompatibility(ServiceContract source, ServiceContract target, boolean ignoreCallback) + throws IncompatibleServiceContractException { + if (source == target) { + // Shortcut for performance + return; + } +// TODO: TUSCANY-1111, this test fails when wiring java to wsdl +// if (source.isRemotable() != target.isRemotable()) { +// throw new IncompatibleServiceContractException("Remotable settings do not match", source, target); +// } + if (source.getInteractionScope() != target.getInteractionScope()) { + throw new IncompatibleServiceContractException("Interaction scopes settings do not match", source, target); + } + + for (Operation operation : source.getOperations().values()) { + Operation targetOperation = target.getOperation(operation.getName()); + if (targetOperation == null) { + throw new IncompatibleServiceContractException("Operation not found on target", source, target); + } + if (!targetOperation.equals(operation)) { + throw new IncompatibleServiceContractException("Target operations are not compatible", source, target); + } + } + + if (ignoreCallback) { + return; + } + + for (Operation operation : source.getCallbackOperations().values()) { + Operation targetOperation = target.getCallbackOperations().get(operation.getName()); + if (targetOperation == null) { + throw new IncompatibleServiceContractException("Callback operation not found on target", + source, + target, + null, + targetOperation); + } + if (!operation.equals(targetOperation)) { + throw new IncompatibleServiceContractException("Target callback operation is not compatible", + source, + target, + operation, + targetOperation); + } + } + } + + + /** + * Creates a wire for flowing outbound invocations from a reference + * + * @param target the reference definition + * @param definition the reference target configuration + * @return the wire the outbound wire + */ + protected List createWire(List targetUris, ComponentReferenceDefinition definition) { + ServiceContract contract = definition.getServiceContract(); + List outboundWires = new ArrayList(); + if (definition.getAssociatedCompTypeRefDefn().isAutowire() || definition.isAutowire()) { + OutboundWire wire = new OutboundWireImpl(); + wire.setAutowire(true); + wire.setServiceContract(contract); + wire.setReferenceName(definition.getName()); + for (Operation operation : contract.getOperations().values()) { + // TODO handle policy + OutboundInvocationChain chain = createOutboundChain(operation); + wire.addInvocationChain(operation, chain); + } + if (contract.getCallbackName() != null) { + wire.setCallbackInterface(contract.getCallbackClass()); + for (Operation operation : contract.getCallbackOperations().values()) { + InboundInvocationChain callbackTargetChain = createInboundChain(operation); + // TODO handle policy + callbackTargetChain.addInterceptor(new InvokerInterceptor()); + wire.addTargetCallbackInvocationChain(operation, callbackTargetChain); + } + } + outboundWires.add(wire); + } else { + for (URI uri : targetUris) { + OutboundWire wire = new OutboundWireImpl(); + QualifiedName qName = new QualifiedName(uri.toString()); + wire.setTargetName(qName); + wire.setServiceContract(contract); + wire.setReferenceName(definition.getName()); + for (Operation operation : contract.getOperations().values()) { + // TODO handle policy + OutboundInvocationChain chain = createOutboundChain(operation); + wire.addInvocationChain(operation, chain); + + } + if (contract.getCallbackName() != null) { + wire.setCallbackInterface(contract.getCallbackClass()); + for (Operation operation : contract.getCallbackOperations().values()) { + InboundInvocationChain callbackTargetChain = createInboundChain(operation); + // TODO handle policy + callbackTargetChain.addInterceptor(new InvokerInterceptor()); + wire.addTargetCallbackInvocationChain(operation, callbackTargetChain); + } + } + outboundWires.add(wire); + } + } + return outboundWires; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java new file mode 100644 index 0000000000..73aa34e6bb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/WireUtils.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.SCAObject; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundChainHolder; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Utilities for operating on wires + * + * @version $Rev$ $Date$ + */ +public final class WireUtils { + + private WireUtils() { + } + + /** + * Maps invocation chains on a wire to corresponding methods + * + * @param wire the wire containing the invocation chains to map + * @param methods the methods to map to + * @return a collection containing the method to invocation chain mapping + * @throws NoMethodForOperationException + */ + public static Map createInboundMapping(InboundWire wire, Method[] methods) + throws NoMethodForOperationException { + Map chains = new HashMap(); + for (Map.Entry, InboundInvocationChain> entry : wire.getInvocationChains().entrySet()) { + Operation operation = entry.getKey(); + InboundInvocationChain chain = entry.getValue(); + Method method = findMethod(operation, methods); + if (method == null) { + throw new NoMethodForOperationException(operation.getName()); + } + chains.put(method, chain); + } + return chains; + } + + + /** + * Maps methods on an interface to operations on a wire + * + * @param interfaze the interface to map from + * @param wire the wire to map to + * @return a collection of method to operation mappings + * @throws NoMethodForOperationException + */ + public static Map createInterfaceToWireMapping(Class interfaze, OutboundWire wire) + throws NoMethodForOperationException { + Map, OutboundInvocationChain> invocationChains = wire.getInvocationChains(); + Map chains = new HashMap(invocationChains.size()); + Method[] methods = interfaze.getMethods(); + for (Map.Entry, OutboundInvocationChain> entry : invocationChains.entrySet()) { + Operation operation = entry.getKey(); + Method method = findMethod(operation, methods); + if (method == null) { + throw new NoMethodForOperationException(operation.getName()); + } + chains.put(method, new OutboundChainHolder(entry.getValue())); + } + return chains; + } + + /** + * Determines if the given wire is optimizable, i.e. its invocation chains may be bypassed during an invocation. + * This is typically calculated during the connect phase to optimize away invocation chains. + * + * @param wire the wire + * @return true if the wire is optimizable + */ + public static boolean isOptimizable(OutboundWire wire) { + for (OutboundInvocationChain chain : wire.getInvocationChains().values()) { + if (chain.getHeadInterceptor() != null) { + Interceptor current = chain.getHeadInterceptor(); + if (current == null) { + break; + } + while (current != null) { + if (!current.isOptimizable()) { + return false; + } + current = current.getNext(); + } + } + } + // if there is a callback, the wire is never optimizable since the callback target needs to be disambiguated + return wire.getTargetCallbackInvocationChains().isEmpty(); + } + + /** + * Determines if the given wire is optimizable, i.e. its invocation chains may be bypassed during an invocation. + * This is typically calculated during the connect phase to optimize away invocation chains. + * + * @param wire the wire + * @return true if the wire is optimizable + */ + public static boolean isOptimizable(InboundWire wire) { + SCAObject container = wire.getContainer(); + if (!(container instanceof Component) || !((Component) container).isOptimizable()) { + return false; + } + for (InboundInvocationChain chain : wire.getInvocationChains().values()) { + if (chain.getHeadInterceptor() != null) { + Interceptor current = chain.getHeadInterceptor(); + while (current != null) { + if (!current.isOptimizable()) { + return false; + } + current = current.getNext(); + } + } + } + return true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java new file mode 100644 index 0000000000..741ef21794 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.Map; + +import org.osoa.sca.NoRegisteredCallbackException; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ReactivationException; +import org.apache.tuscany.spi.component.SCAExternalizable; +import org.apache.tuscany.spi.component.WorkContext; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findOperation; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.AbstractOutboundInvocationHandler; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + + +/** + * Responsible for invoking on an outbound wire associated with a callback. The handler retrieves the correct outbound + * callback wire from the work context. + *

      + * TODO cache target invoker + * + * @version $Rev$ $Date$ + */ +public class JDKCallbackInvocationHandler extends AbstractOutboundInvocationHandler + implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable { + private transient WorkContext context; + private transient InboundWire wire; + private String serviceName; + + /** + * Constructor used for deserialization only + */ + public JDKCallbackInvocationHandler() { + } + + public JDKCallbackInvocationHandler(InboundWire wire, WorkContext context) { + this.context = context; + this.wire = wire; + this.serviceName = wire.getServiceName(); + } + + @SuppressWarnings({"unchecked"}) + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) { + return "[Proxy - " + Integer.toHexString(hashCode()) + "]"; + } else if (method.getDeclaringClass().equals(Object.class) + && "equals".equals(method.getName())) { + // TODO implement + throw new UnsupportedOperationException(); + } else if (Object.class.equals(method.getDeclaringClass()) + && "hashCode".equals(method.getName())) { + return hashCode(); + // TODO beter hash algorithm + } + Object correlationId = context.getCurrentCorrelationId(); + context.setCurrentCorrelationId(null); + LinkedList callbackRoutingChain = (LinkedList) context.getCurrentCallbackRoutingChain().clone(); + if (callbackRoutingChain == null) { + throw new AssertionError("Missing stack of from addresses"); + } + Object targetAddress = callbackRoutingChain.removeFirst(); + if (targetAddress == null) { + throw new AssertionError("Popped a null from address from stack"); + } + //TODO optimize as this is slow in local invocations + Map, OutboundInvocationChain> sourceCallbackInvocationChains = + wire.getSourceCallbackInvocationChains(targetAddress); + Operation operation = findOperation(method, sourceCallbackInvocationChains.keySet()); + OutboundInvocationChain chain = sourceCallbackInvocationChains.get(operation); + TargetInvoker invoker = chain.getTargetInvoker(); + + try { + return invoke(chain, invoker, args, correlationId, callbackRoutingChain); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + if (t instanceof NoRegisteredCallbackException) { + throw t; + } + throw e; + } + } + + + public Object invoke(Method method, Object[] args) throws Throwable { + return invoke(null, method, args); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(serviceName); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + serviceName = (String) in.readObject(); + } + + public void setWorkContext(WorkContext context) { + this.context = context; + } + + public void reactivate() throws ReactivationException { + AtomicComponent owner = context.getCurrentAtomicComponent(); + if (owner == null) { + throw new ReactivationException("Current atomic component not set on work context"); + } + wire = owner.getInboundWire(serviceName); + } +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java new file mode 100644 index 0000000000..d0d82484e3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java @@ -0,0 +1,173 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ReactivationException; +import org.apache.tuscany.spi.component.SCAExternalizable; +import org.apache.tuscany.spi.component.TargetInvocationException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.wire.AbstractInboundInvocationHandler; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + +import org.apache.tuscany.core.wire.WireUtils; + + +/** + * Receives a request from a proxy and performs an invocation on an {@link org.apache.tuscany.spi.wire.InboundWire} via + * an {@link InboundInvocationChain} + * + * @version $Rev$ $Date$ + */ +public final class JDKInboundInvocationHandler extends AbstractInboundInvocationHandler + implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable { + private static final long serialVersionUID = -307902641125881043L; + + /* + * an association of an operation to chain holder. The holder contains the invocation chain + * and a local clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the + * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers + * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker + * is not cacheable, the master associated with the wire chains will be used. + */ + private transient Map chains; + private transient WorkContext context; + private String serviceName; + private Class interfaze; + + /** + * Constructor used for deserialization only + */ + public JDKInboundInvocationHandler() { + } + + public JDKInboundInvocationHandler(Class interfaze, InboundWire wire, WorkContext context) { + this.context = context; + this.serviceName = wire.getServiceName(); + this.interfaze = interfaze; + init(interfaze, wire); + } + + public void setWorkContext(WorkContext context) { + this.context = context; + } + + /** + * Dispatches a client request made on a proxy + */ + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + ChainHolder holder = chains.get(method); + if (holder == null) { + if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) { + return "[Proxy - " + Integer.toHexString(hashCode()) + "]"; + } else if (method.getDeclaringClass().equals(Object.class) + && "equals".equals(method.getName())) { + // TODO implement + throw new UnsupportedOperationException(); + } else if (Object.class.equals(method.getDeclaringClass()) + && "hashCode".equals(method.getName())) { + return hashCode(); + // TODO beter hash algorithm + } + throw new TargetInvocationException("Operation not configured", method.getName()); + } + InboundInvocationChain chain = holder.chain; + TargetInvoker invoker; + if (holder.cachedInvoker == null) { + assert chain != null; + if (chain.getTargetInvoker() == null) { + String name = chain.getOperation().getName(); + throw new TargetInvocationException("No target invoker configured for operation", name); + } + if (chain.getTargetInvoker().isCacheable()) { + // clone and store the invoker locally + holder.cachedInvoker = (TargetInvoker) chain.getTargetInvoker().clone(); + invoker = holder.cachedInvoker; + } else { + invoker = chain.getTargetInvoker(); + } + } else { + assert chain != null; + invoker = chain.getTargetInvoker(); + } + context.setCurrentCorrelationId(null); + return invoke(chain, invoker, args); + } + + + public Object invoke(Method method, Object[] args) throws Throwable { + return invoke(null, method, args); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(serviceName); + out.writeObject(interfaze); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + serviceName = (String) in.readObject(); + interfaze = (Class) in.readObject(); + } + + public void reactivate() throws ReactivationException { + // TODO this method will be extremely slow - look to optimize + AtomicComponent owner = context.getCurrentAtomicComponent(); + if (owner == null) { + throw new ReactivationException("Current atomic component not set on work context"); + } + InboundWire wire = owner.getInboundWire(serviceName); + init(interfaze, wire); + } + + private void init(Class interfaze, InboundWire wire) { + this.chains = new HashMap(); + Method[] methods = interfaze.getMethods(); + Map invocationChains = WireUtils.createInboundMapping(wire, methods); + for (Map.Entry entry : invocationChains.entrySet()) { + this.chains.put(entry.getKey(), new ChainHolder(entry.getValue())); + } + } + + /** + * A holder used to associate an wire chain with a local copy of a target invoker that was previously cloned from + * the chain master + */ + private class ChainHolder { + InboundInvocationChain chain; + TargetInvoker cachedInvoker; + + public ChainHolder(InboundInvocationChain config) { + this.chain = config; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java new file mode 100644 index 0000000000..99cfb3c627 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.osoa.sca.NoRegisteredCallbackException; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ReactivationException; +import org.apache.tuscany.spi.component.SCAExternalizable; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetInvocationException; +import org.apache.tuscany.spi.component.WorkContext; +import static org.apache.tuscany.spi.model.InteractionScope.CONVERSATIONAL; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.AbstractOutboundInvocationHandler; +import org.apache.tuscany.spi.wire.OutboundChainHolder; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + +import org.apache.tuscany.core.implementation.PojoAtomicComponent; +import org.apache.tuscany.core.wire.NoMethodForOperationException; +import org.apache.tuscany.core.wire.WireUtils; + + +/** + * Receives a request from a proxy and performs an invocation on an {@link org.apache.tuscany.spi.wire.OutboundWire} via + * an {@link org.apache.tuscany.spi.wire.OutboundInvocationChain} + * + * @version $Rev$ $Date$ + */ +public final class JDKOutboundInvocationHandler extends AbstractOutboundInvocationHandler + implements WireInvocationHandler, InvocationHandler, Externalizable, SCAExternalizable { + private static final long serialVersionUID = -6155278451964527325L; + + /* + * an association of an operation to chain holder. The holder contains an invocation chain + * and a local clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the + * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers + * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker + * is not cacheable, the master associated with the wire chains will be used. + */ + private transient Map chains; + private transient WorkContext workContext; + private transient Object fromAddress; + private transient boolean wireContainerIsAtomicComponent; + private transient boolean contractHasCallback; + private transient boolean callbackIsImplemented; + private transient String callbackClassName; + private transient boolean contractIsRemotable; + private transient boolean contractIsConversational; + private transient String convIdForRemotableTarget; + private transient String convIdFromThread; + private String referenceName; + private Class interfaze; + + /** + * Constructor used for deserialization only + */ + public JDKOutboundInvocationHandler() { + } + + public JDKOutboundInvocationHandler(Class interfaze, OutboundWire wire, WorkContext workContext) + throws NoMethodForOperationException { + this.workContext = workContext; + this.interfaze = interfaze; + init(interfaze, wire, null); + } + + public JDKOutboundInvocationHandler(Class interfaze, + OutboundWire wire, + Map mapping, + WorkContext workContext) + throws NoMethodForOperationException { + this.workContext = workContext; + this.interfaze = interfaze; + init(interfaze, wire, mapping); + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + OutboundChainHolder holder = chains.get(method); + if (holder == null) { + if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) { + return "[Proxy - " + Integer.toHexString(hashCode()) + "]"; + } else if (method.getDeclaringClass().equals(Object.class) + && "equals".equals(method.getName())) { + // TODO implement + throw new UnsupportedOperationException(); + } else if (Object.class.equals(method.getDeclaringClass()) + && "hashCode".equals(method.getName())) { + return hashCode(); + // TODO beter hash algorithm + } + throw new TargetInvocationException("Operation not configured", method.getName()); + } + OutboundInvocationChain chain = holder.getChain(); + TargetInvoker invoker; + + if (holder.getCachedInvoker() == null) { + assert chain != null; + if (chain.getTargetInvoker() == null) { + String name = chain.getOperation().getName(); + throw new TargetInvocationException("No target invoker configured for operation", name); + } + if (chain.getTargetInvoker().isCacheable()) { + // clone and store the invoker locally + holder.setCachedInvoker((TargetInvoker) chain.getTargetInvoker().clone()); + invoker = holder.getCachedInvoker(); + } else { + invoker = chain.getTargetInvoker(); + } + } else { + assert chain != null; + invoker = chain.getTargetInvoker(); + } + + if (wireContainerIsAtomicComponent && contractHasCallback && !callbackIsImplemented) { + throw new NoRegisteredCallbackException("Instance is does not implement callback: " + + callbackClassName); + } + + if (contractIsConversational) { + assert workContext != null : "Work context cannot be null for conversational invocation"; + // Check for a conv id on thread and remember it + convIdFromThread = (String) workContext.getIdentifier(Scope.CONVERSATION); + if (contractIsRemotable) { + if (convIdForRemotableTarget == null) { + convIdForRemotableTarget = createConversationID(); + } + // Always use the conv id for this target + workContext.setIdentifier(Scope.CONVERSATION, convIdForRemotableTarget); + } else if (convIdFromThread == null) { + String newConvId = createConversationID(); + workContext.setIdentifier(Scope.CONVERSATION, newConvId); + } + } + + Object result = invoke(chain, invoker, args, null, null); + if (contractIsConversational && contractIsRemotable) { + // Make sure we restore the remembered conv id to continue propagating + workContext.setIdentifier(Scope.CONVERSATION, convIdFromThread); + } + return result; + } + + public Object invoke(Method method, Object[] args) throws Throwable { + return invoke(null, method, args); + } + + protected Object getFromAddress() { + return contractHasCallback ? fromAddress : null; + } + + public void setWorkContext(WorkContext context) { + workContext = context; + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(referenceName); + out.writeObject(interfaze); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + referenceName = (String) in.readObject(); + interfaze = (Class) in.readObject(); + } + + public void reactivate() throws ReactivationException { + AtomicComponent owner = workContext.getCurrentAtomicComponent(); + if (owner == null) { + throw new ReactivationException("Current atomic component not set on work context"); + } + List wires = owner.getOutboundWires().get(referenceName); + if (wires == null) { + throw new ReactivationException("Reference wire not found", referenceName, owner.getName()); + } + // TODO handle multiplicity + OutboundWire wire = wires.get(0); + try { + init(interfaze, wire, null); + } catch (NoMethodForOperationException e) { + throw new ReactivationException(e); + } + } + + private void init(Class interfaze, OutboundWire wire, Map mapping) + throws NoMethodForOperationException { + ServiceContract contract = wire.getServiceContract(); + this.referenceName = wire.getReferenceName(); + SCAObject wireContainer = wire.getContainer(); + this.fromAddress = (wireContainer == null) ? null : wireContainer.getName(); + this.contractIsConversational = contract.getInteractionScope().equals(CONVERSATIONAL); + this.contractIsRemotable = contract.isRemotable(); + this.contractHasCallback = contract.getCallbackClass() != null; + if (contractHasCallback) { + this.callbackClassName = contract.getCallbackClass().getName(); + } else { + this.callbackClassName = null; + } + // FIXME JFM this should be done during the callback and not be dependent on PojoAtomicComponent + this.wireContainerIsAtomicComponent = wireContainer instanceof PojoAtomicComponent; + if (wireContainerIsAtomicComponent && contractHasCallback) { + this.callbackIsImplemented = + ((PojoAtomicComponent) wireContainer).implementsCallback(contract.getCallbackClass()); + } else { + this.callbackIsImplemented = false; + } + if (mapping == null) { + chains = WireUtils.createInterfaceToWireMapping(interfaze, wire); + } else { + chains = mapping; + } + } + + // TODO Temporary fix to return a string with a UUID + private String createConversationID() { + return UUID.randomUUID().toString(); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java new file mode 100644 index 0000000000..e15b851351 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +import org.osoa.sca.annotations.Constructor; +import org.osoa.sca.annotations.EagerInit; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.policy.PolicyBuilderRegistry; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundChainHolder; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.ProxyCreationException; +import org.apache.tuscany.spi.wire.Wire; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + +import org.apache.tuscany.core.wire.WireServiceExtension; + +/** + * the default implementation of a wire service that uses JDK dynamic proxies + * + * @version $$Rev$$ $$Date$$ + */ +@EagerInit +public class JDKWireService extends WireServiceExtension { + + public JDKWireService() { + super(null, null); + } + + @Constructor + public JDKWireService(@Autowire WorkContext context, @Autowire PolicyBuilderRegistry policyRegistry) { + super(context, policyRegistry); + } + + public T createProxy(Class interfaze, Wire wire) throws ProxyCreationException { + assert interfaze != null; + assert wire != null; + if (wire instanceof InboundWire) { + InboundWire inbound = (InboundWire) wire; + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(interfaze, inbound, context); + ClassLoader cl = interfaze.getClassLoader(); + return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler)); + } else if (wire instanceof OutboundWire) { + OutboundWire outbound = (OutboundWire) wire; + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(interfaze, outbound, context); + ClassLoader cl = interfaze.getClassLoader(); + return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler)); + } else { + throw new ProxyCreationException("Invalid wire type", wire.getClass().getName()); + } + } + + public T createProxy(Class interfaze, Wire wire, Map mapping) + throws ProxyCreationException { + assert interfaze != null; + assert wire != null; + assert mapping != null; + if (wire instanceof InboundWire) { + InboundWire inbound = (InboundWire) wire; + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(interfaze, inbound, context); + ClassLoader cl = interfaze.getClassLoader(); + return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler)); + } else if (wire instanceof OutboundWire) { + OutboundWire outbound = (OutboundWire) wire; + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(interfaze, outbound, context); + ClassLoader cl = interfaze.getClassLoader(); + return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler)); + } else { + throw new ProxyCreationException("Invalid wire type", wire.getClass().getName()); + } + } + + public Object createCallbackProxy(Class interfaze, InboundWire wire) throws ProxyCreationException { + ClassLoader cl = interfaze.getClassLoader(); + JDKCallbackInvocationHandler handler = new JDKCallbackInvocationHandler(wire, context); + return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler)); + } + + public WireInvocationHandler createHandler(Class interfaze, Wire wire) { + assert wire != null; + if (wire instanceof InboundWire) { + InboundWire inbound = (InboundWire) wire; + return new JDKInboundInvocationHandler(interfaze, inbound, context); + } else if (wire instanceof OutboundWire) { + OutboundWire outbound = (OutboundWire) wire; + return new JDKOutboundInvocationHandler(interfaze, outbound, context); + } else { + throw new ProxyCreationException("Invalid wire type", wire.getClass().getName()); + } + } + +} -- cgit v1.2.3