diff options
Diffstat (limited to 'sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly')
12 files changed, 3123 insertions, 0 deletions
diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java new file mode 100644 index 0000000000..790cc6ec98 --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentReferenceImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentServiceImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl; + + +/** + * The runtime version of assembly factory + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class RuntimeAssemblyFactory extends DefaultAssemblyFactory implements AssemblyFactory { + + public RuntimeAssemblyFactory(ExtensionPointRegistry registry) { + super(registry); + } + + @Override + public Component createComponent() { + return new RuntimeComponentImpl(); + } + + @Override + public ComponentReference createComponentReference() { + return new RuntimeComponentReferenceImpl(); + } + + @Override + public ComponentService createComponentService() { + return new RuntimeComponentServiceImpl(); + } + + @Override + public Endpoint createEndpoint() { + // Create an instance of EndpointImpl that can be serialized/deserialized using the Tuscany + // runtime extension points and extensions + return new RuntimeEndpointImpl(registry); + } + + @Override + public EndpointReference createEndpointReference() { + return new RuntimeEndpointReferenceImpl(registry); + } + +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java new file mode 100644 index 0000000000..db345826d1 --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java @@ -0,0 +1,607 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.RuntimeProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.ActivationException; +import org.apache.tuscany.sca.runtime.CompositeActivator; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeActivatorImpl implements CompositeActivator { + final Logger logger = Logger.getLogger(CompositeActivatorImpl.class.getName()); + + private final ScopeRegistry scopeRegistry; + private final ProviderFactoryExtensionPoint providerFactories; + + public CompositeActivatorImpl(ExtensionPointRegistry extensionPoints) { + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.scopeRegistry = utilities.getUtility(ScopeRegistry.class); + this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class); + } + + //========================================================================= + // Activation + //========================================================================= + + // Composite activation/deactivation + + public void activate(CompositeContext compositeContext, Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + activateComponent(compositeContext, component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + public void deactivate(Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + deactivateComponent(component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + // Component activation/deactivation + + public void activateComponent(CompositeContext compositeContext, Component component) + throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component: " + component.getURI()); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + activate(compositeContext, (Composite) implementation); + } else if (implementation != null) { + addImplementationProvider((RuntimeComponent) component, + implementation); + addScopeContainer(component); + } + + for (ComponentService service : component.getServices()) { + activate(compositeContext, + (RuntimeComponent) component, (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + activate(compositeContext, + (RuntimeComponent) component, (RuntimeComponentReference) reference); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + public void deactivateComponent(Component component) + throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component: " + component.getURI()); + } + for (ComponentService service : component.getServices()) { + deactivate((RuntimeComponent) component, + (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + deactivate((RuntimeComponent) component, + (RuntimeComponentReference) reference); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + deactivate((Composite) implementation); + } else if (implementation != null) { + removeImplementationProvider((RuntimeComponent) component); + removeScopeContainer(component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + // add/remove artifacts required to get the implementation going + + private void addImplementationProvider(RuntimeComponent component, Implementation implementation) { + ImplementationProviderFactory providerFactory = + (ImplementationProviderFactory)providerFactories.getProviderFactory(implementation.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ImplementationProvider implementationProvider = + providerFactory.createImplementationProvider(component, implementation); + if (implementationProvider != null) { + component.setImplementationProvider(implementationProvider); + } + } else { + throw new IllegalStateException("Provider factory not found for class: " + implementation.getClass() + .getName()); + } + for (PolicyProviderFactory f : providerFactories.getPolicyProviderFactories()) { + PolicyProvider policyProvider = f.createImplementationPolicyProvider(component); + if (policyProvider != null) { + component.addPolicyProvider(policyProvider); + } + } + + } + + private void removeImplementationProvider(RuntimeComponent component) { + component.setImplementationProvider(null); + component.getPolicyProviders().clear(); + } + + private void addScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent); + runtimeComponent.setScopeContainer(scopeContainer); + } + + private void removeScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = runtimeComponent.getScopeContainer(); + runtimeComponent.setScopeContainer(null); + } + + + // Service activation/deactivation + + public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentService service) { + if (service.getService() == null) { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Skipping component service not defined in the component type: " + component.getURI() + + "#" + + service.getName()); + } + return; + } + + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component service: " + component.getURI() + "#" + service.getName()); + } + + // Add a wire for each service Endpoint + for ( Endpoint endpoint : service.getEndpoints()){ + RuntimeEndpoint ep = (RuntimeEndpoint) endpoint; + activate(compositeContext, ep); + + // create the interface contract for the binding and service ends of the wire + // that are created as forward only contracts + // FIXME: [rfeng] We might need a better way to get the impl interface contract + Service targetService = service.getService(); + if (targetService == null) { + targetService = service; + } + // endpoint.setInterfaceContract(targetService.getInterfaceContract().makeUnidirectional(false)); + } + } + + public void activate(CompositeContext compositeContext, RuntimeEndpoint ep) { + ep.bind(compositeContext); + + // Check that the service binding interface is compatible with the + // service interface + ep.validateServiceInterfaceCompatibility(); + } + + public void deactivate(RuntimeComponent component, RuntimeComponentService service) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component service: " + component.getURI() + "#" + service.getName()); + } + for(Endpoint ep: service.getEndpoints()) { + if(ep instanceof RuntimeEndpoint) { + deactivate((RuntimeEndpoint) ep); + } + } + } + + public void deactivate(RuntimeEndpoint ep) { + ep.unbind(); + } + + // Reference activation/deactivation + + public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component reference: " + component.getURI() + "#" + reference.getName()); + } + + // set the parent component onto the reference. It's used at start time when the + // reference is asked to return it's runtime wires. If there are none the reference + // asks the component context to start the reference which creates the wires + reference.setComponent(component); + for(EndpointReference epr: reference.getEndpointReferences()) { + activate(compositeContext, (RuntimeEndpointReference) epr); + } + + } + + public void deactivate(RuntimeComponent component, RuntimeComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component reference: " + component.getURI() + "#" + reference.getName()); + } + for(EndpointReference endpointReference: reference.getEndpointReferences()) { + deactivate((RuntimeEndpointReference)endpointReference); + } + } + + public void activate(CompositeContext compositeContext, RuntimeEndpointReference epr) { + // create the wire + // null endpoint passed in here as the endpoint reference may + // not be resolved yet + epr.bind(compositeContext); + + ComponentReference reference = epr.getReference(); + InterfaceContract sourceContract = epr.getComponentTypeReferenceInterfaceContract(); + + // TODO - EPR - interface contract seems to be null in the implementation.web + // case. Not introspecting the CT properly? + if (sourceContract == null){ + // TODO - Can't do this with move of matching to wire + // take the contract from the service to which the reference is connected + sourceContract = ((RuntimeEndpoint) epr.getTargetEndpoint()).getComponentTypeServiceInterfaceContract(); + reference.setInterfaceContract(sourceContract); + } + + // endpointReference.setInterfaceContract(sourceContract.makeUnidirectional(false)); + + // if the reference already has a binding we can check the reference binding interface + // and reference interfaces for compatibility. If we can't check now compatibility + // will be checked when the endpoint reference is resolved. + if (epr.getStatus() == EndpointReference.Status.RESOLVED_BINDING){ + epr.validateReferenceInterfaceCompatibility(); + } + } + + public void deactivate(RuntimeEndpointReference endpointReference) { + endpointReference.unbind(); + } + + //========================================================================= + // Start + //========================================================================= + + // Composite start/stop + + public void start(CompositeContext compositeContext, Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + start(compositeContext, component); + } + + for (Component component : composite.getComponents()) { + if (component instanceof ScopedRuntimeComponent) { + start(compositeContext, (ScopedRuntimeComponent)component); + } + } + } + + public void stop(CompositeContext compositeContext, Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping composite: " + composite.getName()); + } + for (final Component component : composite.getComponents()) { + stop(compositeContext, component); + } + } + + // Component start/stop + + public void start(CompositeContext compositeContext, Component component) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component: " + component.getURI()); + } + RuntimeComponent runtimeComponent = ((RuntimeComponent)component); + if(runtimeComponent.isStarted()) { + return; + } + + compositeContext.bindComponent(runtimeComponent); + Implementation implementation = component.getImplementation(); + + List<RuntimeProvider> providers = new ArrayList<RuntimeProvider>(); + try { + + if (implementation instanceof Composite) { + try { + start(compositeContext, (Composite)implementation); + } catch (Throwable e) { + try { + stop(compositeContext, (Composite) implementation); + } catch (Throwable e1) { + logger.log(Level.SEVERE, e1.getMessage(), e1); + } + rethrow(e); + } + } else { + for (PolicyProvider policyProvider : runtimeComponent.getPolicyProviders()) { + policyProvider.start(); + providers.add(policyProvider); + } + ImplementationProvider implementationProvider = runtimeComponent.getImplementationProvider(); + if (implementationProvider != null) { + implementationProvider.start(); + providers.add(implementationProvider); + } + } + + // Reference bindings aren't started until the wire is first used although this may + // happen when the scope container is started in the case of @EagerInit + + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component service: " + component.getURI() + "#" + service.getName()); + } + for (Endpoint endpoint : service.getEndpoints()) { + RuntimeEndpoint ep = (RuntimeEndpoint)endpoint; + startEndpoint(compositeContext, ep, providers); + } + } + } catch (Throwable e) { + for (int i = providers.size() - 1; i >= 0; i--) { + try { + providers.get(i).stop(); + } catch (Throwable e1) { + logger.log(Level.SEVERE, e1.getMessage(), e1); + } + } + rethrow(e); + } finally { + providers.clear(); + } + + runtimeComponent.setStarted(true); + } + + private void rethrow(Throwable e) throws Error { + if(e instanceof RuntimeException) { + throw (RuntimeException) e; + } else if(e instanceof Error) { + throw (Error) e; + } + } + + public void start(CompositeContext compositeContext, RuntimeEndpoint ep) { + startEndpoint(compositeContext, ep, null); + } + + private void startEndpoint(CompositeContext compositeContext, RuntimeEndpoint ep, final List<RuntimeProvider> providers) { + // FIXME: Should the policy providers be started before the endpoint is started? + for (PolicyProvider policyProvider : ep.getPolicyProviders()) { + policyProvider.start(); + if (providers != null) { + providers.add(policyProvider); + } + } + + final ServiceBindingProvider bindingProvider = ep.getBindingProvider(); + if (bindingProvider != null) { + // bindingProvider.start(); + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.start(); + if (providers != null) { + providers.add(bindingProvider); + } + return null; + } + }); + compositeContext.getEndpointRegistry().addEndpoint(ep); + } + } + + public void stop(CompositeContext compositeContext, Component component) { + if (!((RuntimeComponent)component).isStarted()) { + return; + } + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component: " + component.getURI()); + } + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component service: " + component.getURI() + "#" + service.getName()); + } + for (Endpoint endpoint : service.getEndpoints()) { + RuntimeEndpoint ep = (RuntimeEndpoint) endpoint; + stop(ep); + } + } + for (ComponentReference reference : component.getReferences()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName()); + } + + for (EndpointReference endpointReference : reference.getEndpointReferences()) { + RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference; + stop(epr); + } + } + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + stop(compositeContext, (Composite)implementation); + } else { + final ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider(); + if (implementationProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + implementationProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ((RuntimeComponent)component).getPolicyProviders()) { + policyProvider.stop(); + } + } + + if (component instanceof ScopedRuntimeComponent) { + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + if (runtimeComponent.getScopeContainer() != null && + runtimeComponent.getScopeContainer().getLifecycleState() != ScopeContainer.STOPPED) { + runtimeComponent.getScopeContainer().stop(); + } + } + + ((RuntimeComponent)component).setStarted(false); + } + + public void stop(RuntimeEndpoint ep) { + ep.getCompositeContext().getEndpointRegistry().removeEndpoint(ep); + final ServiceBindingProvider bindingProvider = ep.getBindingProvider(); + if (bindingProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ep.getPolicyProviders()) { + policyProvider.stop(); + } + } + + // Scope container start/stop + // separate off from component start that all endpoints are + // registered before any @EagerInit takes place + public void start(CompositeContext compositeContext, ScopedRuntimeComponent scopedRuntimeComponent) { + if (scopedRuntimeComponent.getScopeContainer() != null) { + scopedRuntimeComponent.getScopeContainer().start(); + } + } + + // Service start/stop + + // done as part of the component start above + + // Reference start/stop + // Used by component context start + + public void start(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference componentReference) { + synchronized (componentReference) { + + if (!(componentReference instanceof RuntimeComponentReference)) { + return; + } + + // create a wire for each endpoint reference. An endpoint reference says either that + // - a target has been specified and hence the reference has been wired in some way. + // - an unwired binding ha been specified + // and endpoint reference representing a wired reference may not at this point + // be resolved (the service to which it points may not be present in the + // current composite). Endpoint reference resolution takes place when the wire + // is first used (when the chains are created) + for (EndpointReference endpointReference : componentReference.getEndpointReferences()){ + // addReferenceWire(compositeContext, endpointReference); + start(compositeContext, (RuntimeEndpointReference) endpointReference); + } + + } + } + + public void start(CompositeContext compositeContext, RuntimeEndpointReference endpointReference) { + compositeContext.getEndpointRegistry().addEndpointReference(endpointReference); + } + + public void stop(Component component, ComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + for ( EndpointReference endpointReference : runtimeRef.getEndpointReferences()){ + RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference; + stop(epr); + } + } + + public void stop(RuntimeEndpointReference epr) { + if (epr.isStarted()) { + CompositeContext compositeContext = epr.getCompositeContext(); + if (compositeContext == null) { + throw new IllegalStateException("The endpoint reference is not bound"); + } + compositeContext.getEndpointRegistry().removeEndpointReference(epr); + ReferenceBindingProvider bindingProvider = epr.getBindingProvider(); + if (bindingProvider != null) { + bindingProvider.stop(); + } + for (PolicyProvider policyProvider : epr.getPolicyProviders()) { + policyProvider.stop(); + } + } + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java new file mode 100644 index 0000000000..aa1a4001a4 --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.runtime.BaseEndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointListener; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * A EndpointRegistry implementation that sees registrations from the same JVM + */ +public class EndpointRegistryImpl extends BaseEndpointRegistry implements EndpointRegistry, LifeCycleListener { + private final Logger logger = Logger.getLogger(EndpointRegistryImpl.class.getName()); + + private List<Endpoint> endpoints = new ArrayList<Endpoint>(); + + public EndpointRegistryImpl(ExtensionPointRegistry extensionPoints, String endpointRegistryURI, String domainURI) { + super(extensionPoints, null, endpointRegistryURI, domainURI); + } + + public synchronized void addEndpoint(Endpoint endpoint) { + endpoints.add(endpoint); + for (EndpointListener listener : listeners) { + listener.endpointAdded(endpoint); + } + logger.info("Add endpoint - " + endpoint.toString()); + } + + public List<Endpoint> findEndpoint(String uri) { + List<Endpoint> foundEndpoints = new ArrayList<Endpoint>(); + for (Endpoint endpoint : endpoints) { + if (endpoint.matches(uri)) { + foundEndpoints.add(endpoint); + logger.fine("Found endpoint with matching service - " + endpoint); + } + // else the service name doesn't match + } + return foundEndpoints; + } + + public synchronized void removeEndpoint(Endpoint endpoint) { + endpoints.remove(endpoint); + endpointRemoved(endpoint); + logger.info("Remove endpoint - " + endpoint.toString()); + } + + public synchronized List<Endpoint> getEndpoints() { + return endpoints; + } + + public synchronized Endpoint getEndpoint(String uri) { + for (Endpoint ep : endpoints) { + String epURI = + ep.getComponent().getURI() + "#" + ep.getService().getName() + "/" + ep.getBinding().getName(); + if (epURI.equals(uri)) { + return ep; + } + if (ep.getBinding().getName() == null || ep.getBinding().getName().equals(ep.getService().getName())) { + epURI = ep.getComponent().getURI() + "#" + ep.getService().getName(); + if (epURI.equals(uri)) { + return ep; + } + } + } + return null; + + } + + public synchronized void updateEndpoint(String uri, Endpoint endpoint) { + Endpoint oldEndpoint = getEndpoint(uri); + if (oldEndpoint == null) { + throw new IllegalArgumentException("Endpoint is not found: " + uri); + } + endpoints.remove(oldEndpoint); + endpoints.add(endpoint); + for (EndpointListener listener : listeners) { + listener.endpointUpdated(oldEndpoint, endpoint); + } + } + + public synchronized void start() { + } + + public synchronized void stop() { + for (Iterator<Endpoint> i = endpoints.iterator(); i.hasNext();) { + Endpoint ep = i.next(); + i.remove(); + endpointRemoved(ep); + } + endpointreferences.clear(); + listeners.clear(); + } + +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java new file mode 100644 index 0000000000..4e5275058e --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.EndpointSerializer; +import org.oasisopen.sca.ServiceRuntimeException; + +public class EndpointSerializerImpl implements EndpointSerializer { + private ExtensionPointRegistry registry; + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessor<Endpoint> processor; + private StAXArtifactProcessor<EndpointReference> refProcessor; + + public EndpointSerializerImpl(ExtensionPointRegistry registry) { + this.registry = registry; + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + inputFactory = factories.getFactory(XMLInputFactory.class); + outputFactory = factories.getFactory(XMLOutputFactory.class); + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + processor = processors.getProcessor(Endpoint.class); + refProcessor = processors.getProcessor(EndpointReference.class); + } + + public Endpoint readEndpoint(String xml) { + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml)); + Endpoint result = processor.read(reader, new ProcessorContext(registry)); + result.setRemote(true); + reader.close(); + return result; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public String write(Endpoint endpoint) { + StringWriter sw = new StringWriter(); + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw); + processor.write(endpoint, writer, new ProcessorContext(registry)); + writer.flush(); + writer.close(); + return sw.toString(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public EndpointReference readEndpointReference(String xml) { + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml)); + EndpointReference result = refProcessor.read(reader, new ProcessorContext(registry)); + reader.close(); + return result; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public String write(EndpointReference endpointReference) { + StringWriter sw = new StringWriter(); + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw); + refProcessor.write(endpointReference, writer, new ProcessorContext(registry)); + writer.flush(); + writer.close(); + return sw.toString(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java new file mode 100644 index 0000000000..b7d83e754a --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.runtime.BaseDomainRegistryFactory; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * The utility responsible for finding the endpoint regstry by the scheme and creating instances for the + * given domain + */ +public class LocalDomainRegistryFactory extends BaseDomainRegistryFactory { + private final static String[] schemes = new String[] {"local", "vm"}; + + /** + * @param extensionRegistry + */ + public LocalDomainRegistryFactory(ExtensionPointRegistry registry) { + super(registry); + } + + protected EndpointRegistry createEndpointRegistry(String endpointRegistryURI, String domainURI) { + EndpointRegistry endpointRegistry = + new EndpointRegistryImpl(registry, endpointRegistryURI, domainURI); + return endpointRegistry; + } + + public String[] getSupportedSchemes() { + return schemes; + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java new file mode 100644 index 0000000000..4d6a98ca5f --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * Artifact processor for reference parameters. + * + * @version $Rev$ $Date$ + */ +public class ReferenceParameterProcessor implements StAXArtifactProcessor<ReferenceParameters> { + private static final QName REFERENCE_PARAMETERS = + new QName("http://tuscany.apache.org/xmlns/sca/1.1", "referenceParameters", "tuscany"); + + /** + * Constructs a new processor. + * + * @param modelFactories + */ + public ReferenceParameterProcessor(FactoryExtensionPoint modelFactories) { + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#getArtifactType() + */ + public QName getArtifactType() { + return REFERENCE_PARAMETERS; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#read(javax.xml.stream.XMLStreamReader, ProcessorContext) + */ + public ReferenceParameters read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + ReferenceParameters parameters = new ReferenceParametersImpl(); + parameters.setCallbackID(reader.getAttributeValue(null, "callbackID")); + return parameters; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#write(java.lang.Object, javax.xml.stream.XMLStreamWriter, ProcessorContext) + */ + public void write(ReferenceParameters model, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, + XMLStreamException { + writer.writeStartElement(REFERENCE_PARAMETERS.getPrefix(), + REFERENCE_PARAMETERS.getLocalPart(), + REFERENCE_PARAMETERS.getNamespaceURI()); + writer.writeNamespace(REFERENCE_PARAMETERS.getPrefix(), REFERENCE_PARAMETERS.getNamespaceURI()); + + if (model.getCallbackID() != null) { + writer.writeAttribute("callbackID", model.getCallbackID().toString()); + } + writer.writeEndElement(); + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#getModelType() + */ + public Class<ReferenceParameters> getModelType() { + return ReferenceParameters.class; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#resolve(java.lang.Object, org.apache.tuscany.sca.contribution.resolver.ModelResolver, ProcessorContext) + */ + public void resolve(ReferenceParameters model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + } + +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java new file mode 100644 index 0000000000..7bd56271a5 --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * @version $Rev$ $Date$ + */ +public class ReferenceParametersImpl implements ReferenceParameters { + private Object callbackID; + private EndpointReference callbackReference; + private Object callbackObjectID; + + /** + * @return the callbackID + */ + public Object getCallbackID() { + return callbackID; + } + /** + * @param callbackID the callbackID to set + */ + public void setCallbackID(Object callbackID) { + this.callbackID = callbackID; + } + + /** + * @see org.apache.tuscany.sca.runtime.ReferenceParameters#getCallbackReference() + */ + public EndpointReference getCallbackReference() { + return callbackReference; + } + /** + * @see org.apache.tuscany.sca.runtime.ReferenceParameters#setCallback(java.lang.Object) + */ + public void setCallbackReference(EndpointReference callback) { + this.callbackReference = callback; + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + /** + * @return the callbackObjectID + */ + public Object getCallbackObjectID() { + return callbackObjectID; + } + /** + * @param callbackObjectID the callbackObjectID to set + */ + public void setCallbackObjectID(Object callbackObjectID) { + this.callbackObjectID = callbackObjectID; + } + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((callbackID == null) ? 0 : callbackID.hashCode()); + result = prime * result + ((callbackObjectID == null) ? 0 : callbackObjectID.hashCode()); + result = prime * result + ((callbackReference == null) ? 0 : callbackReference.hashCode()); + return result; + } + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ReferenceParametersImpl)) + return false; + final ReferenceParametersImpl other = (ReferenceParametersImpl)obj; + if (callbackID == null) { + if (other.callbackID != null) + return false; + } else if (!callbackID.equals(other.callbackID)) + return false; + if (callbackObjectID == null) { + if (other.callbackObjectID != null) + return false; + } else if (!callbackObjectID.equals(other.callbackObjectID)) + return false; + if (callbackReference == null) { + if (other.callbackReference != null) + return false; + } else if (!callbackReference.equals(other.callbackReference)) + return false; + + return true; + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java new file mode 100644 index 0000000000..a71c823c11 --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.impl.ComponentImpl; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ResolverExtension; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class RuntimeComponentImpl extends ComponentImpl implements RuntimeComponent, + ScopedRuntimeComponent, ResolverExtension { + protected RuntimeComponentContext componentContext; + protected ImplementationProvider implementationProvider; + protected List<PolicyProvider> policyProviders = new ArrayList<PolicyProvider>(); + protected ScopeContainer scopeContainer; + protected boolean started; + protected ModelResolver modelResolver; + + /** + */ + public RuntimeComponentImpl() { + super(); + } + + public ImplementationProvider getImplementationProvider() { + return implementationProvider; + } + + public void setImplementationProvider(ImplementationProvider provider) { + this.implementationProvider = provider; + } + + public ScopeContainer getScopeContainer() { + return scopeContainer; + } + + public void setScopeContainer(ScopeContainer scopeContainer) { + this.scopeContainer = scopeContainer; + } + + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + /** + * @return the componentContext + */ + public RuntimeComponentContext getComponentContext() { + return componentContext; + } + + /** + * @param componentContext the componentContext to set + */ + public void setComponentContext(RuntimeComponentContext componentContext) { + this.componentContext = componentContext; + } + + public void addPolicyProvider(PolicyProvider policyProvider) { + policyProviders.add(policyProvider); + } + + public List<PolicyProvider> getPolicyProviders() { + return policyProviders; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + @Override + public String toString() { + return getName(); + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String serviceName) { + RuntimeComponentContext componentContext = null; + + // If the component is a composite, then we need to find the + // non-composite component that provides the requested service + if (getImplementation() instanceof Composite) { + for (ComponentService componentService : getServices()) { + String bindingName = null; + if (serviceName != null) { + int index = serviceName.indexOf('/'); + if (index != -1) { + bindingName = serviceName.substring(index + 1); + serviceName = serviceName.substring(0, index); + } + } + if (serviceName == null || serviceName.equals(componentService.getName())) { + CompositeService compositeService = (CompositeService)componentService.getService(); + if (compositeService != null) { + componentContext = + ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext(); + serviceName = compositeService.getPromotedService().getName(); + if (bindingName != null) { + serviceName = serviceName + "/" + bindingName; + } + return componentContext.createSelfReference(businessInterface, serviceName); + } + break; + } + } + // No matching service found + throw new ServiceRuntimeException("Composite service not found: " + serviceName); + } else { + componentContext = getComponentContext(); + if (serviceName != null) { + return componentContext.createSelfReference(businessInterface, serviceName); + } else { + return componentContext.createSelfReference(businessInterface); + } + } + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java new file mode 100644 index 0000000000..2eea60ccea --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; + +/** + * Implementation of a Component Reference. + * + * @version $Rev$ $Date$ + */ +public class RuntimeComponentReferenceImpl extends ComponentReferenceImpl implements RuntimeComponentReference { + + private RuntimeComponent component; + + public RuntimeComponentReferenceImpl() { + super(); + } + + /** + * @return the component + */ + public RuntimeComponent getComponent() { + return component; + } + + /** + * @param component the component to set + */ + public void setComponent(RuntimeComponent component) { + this.component = component; + } + + /** + * @see org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeComponentReferenceImpl ref = (RuntimeComponentReferenceImpl)super.clone(); + return ref; + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java new file mode 100644 index 0000000000..bc7e6df878 --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Implementation of a Component Service. + * + * @version $Rev$ $Date$ + */ +public class RuntimeComponentServiceImpl extends ComponentServiceImpl implements RuntimeComponentService { + + public RuntimeComponentServiceImpl() { + super(); + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java new file mode 100644 index 0000000000..6339b96a1b --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java @@ -0,0 +1,941 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.StringReader; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.assembly.impl.EndpointImpl; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.RuntimeInvoker; +import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl; +import org.apache.tuscany.sca.core.invocation.impl.PhaseManager; +import org.apache.tuscany.sca.interfacedef.Compatibility; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InterceptorAsync; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.InvokerAsyncResponse; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.EndpointAsyncProvider; +import org.apache.tuscany.sca.provider.EndpointProvider; +import org.apache.tuscany.sca.provider.ImplementationAsyncProvider; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointSerializer; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Runtime model for Endpoint that supports java serialization + */ +public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint, Externalizable { + private static final long serialVersionUID = 1L; + private transient CompositeContext compositeContext; + private transient RuntimeWireProcessor wireProcessor; + private transient ProviderFactoryExtensionPoint providerFactories; + private transient InterfaceContractMapper interfaceContractMapper; + private transient WorkScheduler workScheduler; + private transient PhaseManager phaseManager; + private transient MessageFactory messageFactory; + private transient RuntimeInvoker invoker; + private transient EndpointSerializer serializer; + + private transient List<InvocationChain> chains; + private transient Map<Operation, InvocationChain> invocationChainMap = + new ConcurrentHashMap<Operation, InvocationChain>(); + private transient InvocationChain bindingInvocationChain; + + private transient ServiceBindingProvider bindingProvider; + private transient List<PolicyProvider> policyProviders; + private String xml; + + protected InterfaceContract bindingInterfaceContract; + protected InterfaceContract serviceInterfaceContract; + + /** + * No-arg constructor for Java serialization + */ + public RuntimeEndpointImpl() { + super(null); + } + + public RuntimeEndpointImpl(ExtensionPointRegistry registry) { + super(registry); + } + + protected void copyFrom(RuntimeEndpointImpl copy) { + this.xml = copy.xml; + + this.component = copy.component; + this.service = copy.service; + this.interfaceContract = copy.interfaceContract; + this.serviceInterfaceContract = copy.serviceInterfaceContract; + + this.binding = copy.binding; + this.bindingInterfaceContract = copy.interfaceContract; + this.bindingInvocationChain = copy.bindingInvocationChain; + + this.callbackEndpointReferences = copy.callbackEndpointReferences; + + this.requiredIntents = copy.requiredIntents; + this.policySets = copy.policySets; + + this.uri = copy.uri; + this.remote = copy.remote; + this.unresolved = copy.unresolved; + + this.chains = copy.chains; + this.invocationChainMap = copy.invocationChainMap; + this.bindingProvider = copy.bindingProvider; + this.policyProviders = copy.policyProviders; + + if (this.compositeContext == null && copy.compositeContext != null) { + bind(copy.compositeContext); + } + } + + public void bind(CompositeContext compositeContext) { + this.compositeContext = compositeContext; + bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry()); + } + + public void bind(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry) { + if (compositeContext == null) { + compositeContext = new CompositeContext(registry, endpointRegistry); + } + this.registry = registry; + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + this.wireProcessor = + new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); + + this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class); + this.invoker = new RuntimeInvoker(registry, this); + + this.phaseManager = utilities.getUtility(PhaseManager.class); + this.serializer = utilities.getUtility(EndpointSerializer.class); + this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + this.contractBuilder = builders.getContractBuilder(); + } + + public void unbind() { + compositeContext = null; + bindingInvocationChain = null; + chains = null; + bindingProvider = null; + policyProviders = null; + invocationChainMap.clear(); + } + + public synchronized List<InvocationChain> getInvocationChains() { + if (chains == null) { + initInvocationChains(); + } + return chains; + } + + public synchronized InvocationChain getBindingInvocationChain() { + if (bindingInvocationChain == null) { + bindingInvocationChain = new InvocationChainImpl(null, null, false, phaseManager, isAsyncInvocation()); + initServiceBindingInvocationChains(); + } + + // Init the operation invocation chains now. We know they will + // be needed as well as the binding invocation chain and this + // makes the wire processors run + getInvocationChains(); + + return bindingInvocationChain; + } + + /** + * A dummy invocation chain representing null as ConcurrentHashMap doesn't allow null values + */ + private static final InvocationChain NULL_CHAIN = new InvocationChainImpl(null, null, false, null, false); + + public InvocationChain getInvocationChain(Operation operation) { + InvocationChain cached = invocationChainMap.get(operation); + if (cached == null) { + for (InvocationChain chain : getInvocationChains()) { + Operation op = chain.getTargetOperation(); + + // We used to check compatibility here but this is now validated when the + // chain is created. As the chain operations are the real interface types + // they may be incompatible just because they are described in different + // IDLs + if (operation.getInterface().isRemotable()) { + if (operation.getName().equals(op.getName())) { + invocationChainMap.put(operation, chain); + return chain; + } + if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) { + invocationChainMap.put(operation, chain); + return chain; + } + } else { + // [rfeng] We need to run the compatibility check for local operations as they + // can be overloaded + if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) { + invocationChainMap.put(operation, chain); + return chain; + } + } + } + // Cache it with the NULL_CHAIN to avoid NPE + invocationChainMap.put(operation, NULL_CHAIN); + return null; + } else { + if (cached == NULL_CHAIN) { + cached = null; + } + return cached; + } + } + + public Message invoke(Message msg) { + // Deal with async callback + // Ensure invocation chains are built... + getInvocationChains(); + if ( !this.getCallbackEndpointReferences().isEmpty() ) { + RuntimeEndpointReference asyncEPR = (RuntimeEndpointReference) this.getCallbackEndpointReferences().get(0); + // Place a link to the callback EPR into the message headers... + msg.getHeaders().put("ASYNC_CALLBACK", asyncEPR ); + } + // end of async callback handling + return invoker.invokeBinding(msg); + } + + public Object invoke(Operation operation, Object[] args) throws InvocationTargetException { + return invoker.invoke(operation, args); + } + + public Message invoke(Operation operation, Message msg) { + return invoker.invoke(operation, msg); + } + + public void invokeAsync(Message msg){ + invoker.invokeBindingAsync(msg); + } // end method invokeAsync(Message) + + public void invokeAsync(Operation operation, Message msg){ + msg.setOperation(operation); + invoker.invokeAsync(msg); + } // end method invokeAsync(Operation, Message) + + public void invokeAsyncResponse(Message msg){ + invoker.invokeAsyncResponse(msg); + } + + /** + * Navigate the component/componentType inheritance chain to find the leaf contract + * @param contract + * @return + */ + private Contract getLeafContract(Contract contract) { + Contract prev = null; + Contract current = contract; + while (current != null) { + prev = current; + if (current instanceof ComponentReference) { + current = ((ComponentReference)current).getReference(); + } else if (current instanceof CompositeReference) { + current = ((CompositeReference)current).getPromotedReferences().get(0); + } else if (current instanceof ComponentService) { + current = ((ComponentService)current).getService(); + } else if (current instanceof CompositeService) { + current = ((CompositeService)current).getPromotedService(); + } else { + break; + } + if (current == null) { + return prev; + } + } + return current; + } + + /** + * Initialize the invocation chains + */ + private void initInvocationChains() { + chains = new ArrayList<InvocationChain>(); + InterfaceContract sourceContract = getBindingInterfaceContract(); + + // It's the service wire + RuntimeComponentService service = (RuntimeComponentService)getService(); + RuntimeComponent serviceComponent = (RuntimeComponent)getComponent(); + + //InterfaceContract targetContract = getInterfaceContract(); + // TODO - EPR - why is this looking at the component types. The endpoint should have the right interface contract by this time + InterfaceContract targetContract = getComponentTypeServiceInterfaceContract(); + // setInterfaceContract(targetContract); + validateServiceInterfaceCompatibility(); + for (Operation operation : sourceContract.getInterface().getOperations()) { + Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation); + if (targetOperation == null) { + throw new ServiceRuntimeException("No matching operation for " + operation.getName() + + " is found in service " + + serviceComponent.getURI() + + "#" + + service.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, false, phaseManager, isAsyncInvocation()); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(chain); + } + addServiceBindingInterceptor(chain, operation); + addImplementationInterceptor(serviceComponent, service, chain, targetOperation); + chains.add(chain); + + // Handle cases where the operation is an async server + if( targetOperation.isAsyncServer() ) { + createAsyncServerCallback( this, operation ); + } // end if + } + + wireProcessor.process(this); + + // If we have to support async and there is no binding chain + // then set the response path to point directly to the + // binding provided async response handler + if (isAsyncInvocation() && + bindingInvocationChain == null){ + // fix up the operation chain response path to point back to the + // binding provided async response handler + ServiceBindingProvider serviceBindingProvider = getBindingProvider(); + if (serviceBindingProvider instanceof EndpointAsyncProvider){ + EndpointAsyncProvider asyncEndpointProvider = (EndpointAsyncProvider)serviceBindingProvider; + InvokerAsyncResponse asyncResponseInvoker = asyncEndpointProvider.createAsyncResponseInvoker(); + + for (InvocationChain chain : getInvocationChains()){ + Invoker invoker = chain.getHeadInvoker(); + if (invoker instanceof InterceptorAsync){ + ((InterceptorAsync)invoker).setPrevious(asyncResponseInvoker); + } else { + //TODO - throw error once the old async code is removed + } + } + } else { + // TODO - throw error once the old async code is removed + } + } + } + + /** + * Creates the async callback for the supplied Endpoint and Operation, if it does not already exist + * and stores it into the Endpoint + * @param endpoint - the Endpoint + * @param operation - the Operation + */ + private void createAsyncServerCallback( RuntimeEndpoint endpoint, Operation operation ) { + // Check to see if the callback already exists + if( asyncCallbackExists( endpoint ) ) return; + + RuntimeEndpointReference asyncEPR = createAsyncEPR( endpoint ); + + // Store the new callback EPR into the Endpoint + endpoint.getCallbackEndpointReferences().add(asyncEPR); + } // end method createAsyncServerCallback + + /** + * Creates the Endpoint object for the async callback + * @param endpoint - the endpoint which has the async server operations + * @return the EndpointReference object representing the callback + */ + private RuntimeEndpointReference createAsyncEPR( RuntimeEndpoint endpoint ){ + CompositeContext compositeContext = endpoint.getCompositeContext(); + RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory( compositeContext ); + RuntimeEndpointReference epr = (RuntimeEndpointReference)assemblyFactory.createEndpointReference(); + epr.bind( compositeContext ); + + // Create pseudo-reference + ComponentReference reference = assemblyFactory.createComponentReference(); + ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class); + JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + try { + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseHandler.class)); + } catch (InvalidInterfaceException e1) { + // Nothing to do here - will not happen + } // end try + reference.setInterfaceContract(interfaceContract); + String referenceName = endpoint.getService().getName() + "_asyncCallback"; + reference.setName(referenceName); + reference.setForCallback(true); + // Add in "implementation" reference (really a dummy, but with correct interface) + Reference implReference = assemblyFactory.createReference(); + implReference.setInterfaceContract(interfaceContract); + implReference.setName(referenceName); + implReference.setForCallback(true); + + reference.setReference(implReference); + // Set the created ComponentReference into the EPR + epr.setReference(reference); + + // Create a binding + Binding binding = createMatchingBinding( endpoint.getBinding(), (RuntimeComponent)endpoint.getComponent(), reference, registry ); + epr.setBinding(binding); + + // Need to establish policies here (binding has some...) + epr.getRequiredIntents().addAll( endpoint.getRequiredIntents() ); + epr.getPolicySets().addAll( endpoint.getPolicySets() ); + String eprURI = endpoint.getComponent().getName() + "#reference-binding(" + referenceName + "/" + referenceName + ")"; + epr.setURI(eprURI); + + // Attach a dummy endpoint to the epr + RuntimeEndpoint ep = (RuntimeEndpoint)assemblyFactory.createEndpoint(); + ep.setUnresolved(false); + epr.setTargetEndpoint(ep); + //epr.setStatus(EndpointReference.Status.RESOLVED_BINDING); + epr.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED); + epr.setUnresolved(false); + + return epr; + } // end method RuntimeEndpointReference + + private boolean asyncCallbackExists( RuntimeEndpoint endpoint ) { + if( endpoint.getCallbackEndpointReferences().isEmpty() ) return false; + return true; + } // end method asyncCallbackExists + + /** + * Create a matching binding to a supplied binding + * - the matching binding has the same binding type, but is for the supplied component and service + * @param matchBinding - the binding to match + * @param component - the component + * @param service - the service + * @param registry - registry for extensions + * @return - the matching binding, or null if it could not be created + */ + @SuppressWarnings("unchecked") + private Binding createMatchingBinding( Binding matchBinding, RuntimeComponent component, + ComponentReference reference, ExtensionPointRegistry registry ) { + // Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of + // time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName + // and then read the XML using the processor for that XML... + QName bindingName = matchBinding.getType(); + String bindingXML = "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>"; + + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName); + + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class); + StreamSource source = new StreamSource( new StringReader(bindingXML) ); + + ProcessorContext context = new ProcessorContext(); + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(source); + reader.next(); + Binding newBinding = (Binding) processor.read(reader, context ); + newBinding.setName("asyncCallback"); + + // Create a URI address for the callback based on the Component_Name/Reference_Name pattern + String callbackURI = "/" + component.getName() + "/" + reference.getName(); + //newBinding.setURI(callbackURI); + + BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + BindingBuilder builder = builders.getBindingBuilder(newBinding.getType()); + if (builder != null) { + org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry); + builder.build(component, reference, newBinding, builderContext, true); + } // end if + + return newBinding; + } catch (ContributionReadException e) { + e.printStackTrace(); + } catch (XMLStreamException e) { + e.printStackTrace(); + } + + return null; + } // end method createMatchingBinding + + /** + * Gets a RuntimeAssemblyFactory from the CompositeContext + * @param compositeContext + * @return the RuntimeAssemblyFactory + */ + private RuntimeAssemblyFactory getAssemblyFactory( CompositeContext compositeContext ) { + ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + } // end method RuntimeAssemblyFactory + + /** + * Check that endpoint has compatible interface at the component and binding ends. + * The user can specify the interfaces at both ends so there is a danger that they won't be compatible. + */ + public void validateServiceInterfaceCompatibility() { + + InterfaceContract serviceContract = getComponentServiceInterfaceContract(); + InterfaceContract bindingContract = getBindingInterfaceContract(); + + if ((serviceContract != null) && + (bindingContract != null)){ + + boolean bindingHasCallback = bindingContract.getCallbackInterface() != null; + + try { + + // Use the normalized contract if the interface types are different or if + // a normalized contract has been previously generate, for example, by virtue + // of finding a JAXWS annotation on a Java class that references a WSDL file + if (serviceContract.getClass() != bindingContract.getClass() || + serviceContract.getNormalizedWSDLContract() != null || + bindingContract.getNormalizedWSDLContract() != null) { + interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(serviceContract), + getGeneratedWSDLContract(bindingContract), + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } else { + interfaceContractMapper.checkCompatibility(serviceContract, + bindingContract, + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } + } catch (Exception ex){ + throw new ServiceRuntimeException("Component " + + this.getComponent().getName() + + " Service " + + getService().getName() + + " interface is incompatible with the interface of the service binding - " + + getBinding().getName() + + " - " + + ex.getMessage() + + " - [" + this.toString() + "]"); + } + } + + } + + private void initServiceBindingInvocationChains() { + + // add the binding interceptors to the service binding wire + ServiceBindingProvider provider = getBindingProvider(); + if ((provider != null) && (provider instanceof EndpointProvider)) { + ((EndpointProvider)provider).configure(); + } + + // add the policy interceptors to the service binding wire + List<PolicyProvider> pps = getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createBindingInterceptor(); + if (interceptor != null) { + bindingInvocationChain.addInterceptor(interceptor); + } + } + + } + + // This is strategically placed before the RuntimeInvoker is added to the end of the + // binding chain as the RuntimeInvoker doesn't need to take part in the response + // processing and doesn't implement InvokerAsyncResponse + if (isAsyncInvocation()){ + // fix up the invocation chains to point back to the + // binding chain so that async response messages + // are processed correctly + for (InvocationChain chain : getInvocationChains()){ + Invoker invoker = chain.getHeadInvoker(); + if (invoker instanceof InterceptorAsync){ + ((InterceptorAsync)invoker).setPrevious((InvokerAsyncResponse)bindingInvocationChain.getTailInvoker()); + } else { + // TODO - raise an error. Not doing that while + // we have the old async mechanism in play + } + } + + // fix up the binding chain response path to point back to the + // binding provided async response handler + ServiceBindingProvider serviceBindingProvider = getBindingProvider(); + if (serviceBindingProvider instanceof EndpointAsyncProvider){ + EndpointAsyncProvider asyncEndpointProvider = (EndpointAsyncProvider)serviceBindingProvider; + InvokerAsyncResponse asyncResponseInvoker = asyncEndpointProvider.createAsyncResponseInvoker(); + if (bindingInvocationChain.getHeadInvoker() instanceof InterceptorAsync){ + ((InterceptorAsync)bindingInvocationChain.getHeadInvoker()).setPrevious(asyncResponseInvoker); + } else { + //TODO - throw error once the old async code is removed + } + } else { + //TODO - throw error once the old async code is removed + } + } + + // Add the runtime invoker to the end of the binding chain. + // It mediates between the binding chain and selects the + // correct invocation chain based on the operation that's + // been selected + bindingInvocationChain.addInvoker(invoker); + } + + /** + * Add the interceptor for a binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addServiceBindingInterceptor(InvocationChain chain, Operation operation) { + List<PolicyProvider> pps = getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + } + } + } + + /** + * Add a non-blocking interceptor if the service binding needs it + * + * @param service + * @param binding + * @param chain + */ + private void addNonBlockingInterceptor(InvocationChain chain) { + ServiceBindingProvider provider = getBindingProvider(); + if (provider != null) { + if (!provider.supportsOneWayInvocation()) { + chain.addInterceptor(Phase.SERVICE, new NonBlockingInterceptor(workScheduler)); + } + } + } + + /** + * Add the interceptor for a component implementation + * + * @param component + * @param service + * @param chain + * @param operation + */ + private void addImplementationInterceptor(Component component, + ComponentService service, + InvocationChain chain, + Operation operation) { + + if (service.getService() instanceof CompositeService) { + CompositeService compositeService = (CompositeService)service.getService(); + component = getPromotedComponent(compositeService); + service = getPromotedComponentService(compositeService); + } + + ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider(); + + if (provider != null) { + Invoker invoker = null; + RuntimeComponentService runtimeService = (RuntimeComponentService)service; + if (runtimeService.getName().endsWith("_asyncCallback")){ + if (provider instanceof ImplementationAsyncProvider){ + invoker = (Invoker)((ImplementationAsyncProvider)provider).createAsyncResponseInvoker(operation); + } else { + // TODO - This should be an error but taking account of the + // existing non-native async support + invoker = provider.createInvoker((RuntimeComponentService)service, operation); +/* + throw new ServiceRuntimeException("Component " + + this.getComponent().getName() + + " Service " + + getService().getName() + + " implementation provider doesn't implement ImplementationAsyncProvider but the implementation uses a " + + "refrence interface with the asyncInvocation intent set" + + " - [" + this.toString() + "]"); +*/ + } + } else if (isAsyncInvocation() && + provider instanceof ImplementationAsyncProvider){ + invoker = (Invoker)((ImplementationAsyncProvider)provider).createAsyncInvoker((RuntimeComponentService)service, operation); + } else { + invoker = provider.createInvoker((RuntimeComponentService)service, operation); + } + chain.addInvoker(invoker); + } + // TODO - EPR - don't we need to get the policy from the right level in the + // model rather than the leafmost level + List<PolicyProvider> pps = ((RuntimeComponent)component).getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + } + } + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeEndpointImpl copy = (RuntimeEndpointImpl)super.clone(); + copy.invoker = new RuntimeInvoker(registry, copy); + return copy; + } + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + private ComponentService getPromotedComponentService(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponentService((CompositeService)service); + + } else { + + // Found a non-composite service + return componentService; + } + } else { + + // No promoted service + return null; + } + } + + /** + * Follow a service promotion chain down to the innermost (non-composite) component. + * + * @param compositeService + * @return + */ + private Component getPromotedComponent(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponent((CompositeService)service); + + } else { + + // Found a non-composite service + return compositeService.getPromotedComponent(); + } + } else { + + // No promoted service + return null; + } + } + + public synchronized ServiceBindingProvider getBindingProvider() { + resolve(); + if (bindingProvider == null) { + BindingProviderFactory factory = + (BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass()); + if (factory == null) { + throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding() + .getType()); + } + this.bindingProvider = factory.createServiceBindingProvider(this); + } + return bindingProvider; + } + + public synchronized List<PolicyProvider> getPolicyProviders() { + resolve(); + if (policyProviders == null) { + policyProviders = new ArrayList<PolicyProvider>(); + for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) { + PolicyProvider provider = factory.createServicePolicyProvider(this); + if (provider != null) { + policyProviders.add(provider); + } + } + } + return policyProviders; + } + + public void setBindingProvider(ServiceBindingProvider provider) { + this.bindingProvider = provider; + } + + public Contract getContract() { + return getService(); + } + + public CompositeContext getCompositeContext() { + return compositeContext; + } + + @Override + protected void reset() { + super.reset(); + this.xml = null; + } + + @Override + protected synchronized void resolve() { + if (xml != null && component == null) { + if (compositeContext == null) { + compositeContext = CompositeContext.getCurrentCompositeContext(); + if (compositeContext != null) { + bind(compositeContext); + } + } + if (serializer != null) { + RuntimeEndpointImpl ep = (RuntimeEndpointImpl)serializer.readEndpoint(xml); + copyFrom(ep); + } else { + // FIXME: [rfeng] What should we do here? + } + } + super.resolve(); + } + + public InterfaceContract getBindingInterfaceContract() { + resolve(); + if (bindingInterfaceContract != null) { + return bindingInterfaceContract; + } + bindingInterfaceContract = getBindingProvider().getBindingInterfaceContract(); + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentServiceInterfaceContract(); + } + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentTypeServiceInterfaceContract(); + } + return bindingInterfaceContract; + } + + public InterfaceContract getComponentTypeServiceInterfaceContract() { + resolve(); + if (serviceInterfaceContract != null) { + return serviceInterfaceContract; + } + if (service == null) { + return getComponentServiceInterfaceContract(); + } + serviceInterfaceContract = getLeafContract(service).getInterfaceContract(); + if (serviceInterfaceContract == null) { + serviceInterfaceContract = getComponentServiceInterfaceContract(); + } + return serviceInterfaceContract; + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.uri = in.readUTF(); + this.xml = in.readUTF(); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(getURI()); + if (serializer == null && xml != null) { + out.writeUTF(xml); + } else { + if (serializer != null) { + out.writeUTF(serializer.write(this)); + } else { + throw new IllegalStateException("No serializer is configured"); + } + } + } + public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) { + + if ( interfaceContract.getNormalizedWSDLContract() == null){ + if (getComponentServiceInterfaceContract() instanceof JavaInterfaceContract){ + if (contractBuilder == null){ + throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString()); + } + contractBuilder.build(interfaceContract, null); + } + } + + return interfaceContract.getNormalizedWSDLContract(); + } +} diff --git a/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java new file mode 100644 index 0000000000..89d0e444af --- /dev/null +++ b/sandbox/sebastien/java/vhost/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java @@ -0,0 +1,743 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.assembly.impl.EndpointReferenceImpl; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.RuntimeInvoker; +import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl; +import org.apache.tuscany.sca.core.invocation.impl.PhaseManager; +import org.apache.tuscany.sca.interfacedef.Compatibility; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InterceptorAsync; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.InvokerAsyncResponse; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.EndpointReferenceProvider; +import org.apache.tuscany.sca.provider.ImplementationAsyncProvider; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointSerializer; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Runtime model for Endpoint that supports java serialization + */ +public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implements RuntimeEndpointReference, Externalizable { + private transient CompositeContext compositeContext; + private transient RuntimeWireProcessor wireProcessor; + private transient InterfaceContractMapper interfaceContractMapper; + private transient WorkScheduler workScheduler; + private transient PhaseManager phaseManager; + private transient MessageFactory messageFactory; + private transient RuntimeInvoker invoker; + private transient EndpointRegistry endpointRegistry; + + private transient List<InvocationChain> chains; + private transient Map<Operation, InvocationChain> invocationChainMap = + new ConcurrentHashMap<Operation, InvocationChain>(); + private transient InvocationChain bindingInvocationChain; + + private transient EndpointReferenceBinder eprBinder; + private transient ReferenceBindingProvider bindingProvider; + private transient ProviderFactoryExtensionPoint providerFactories; + private transient List<PolicyProvider> policyProviders; + private transient EndpointSerializer serializer; + + protected InterfaceContract bindingInterfaceContract; + protected InterfaceContract referenceInterfaceContract; + + //protected InterfaceContract generatedReferenceWSDLInterfaceContract; + + private String xml; + + private boolean started; + + /** + * No-arg constructor for Java serilization + */ + public RuntimeEndpointReferenceImpl() { + super(null); + } + + public RuntimeEndpointReferenceImpl(ExtensionPointRegistry registry) { + super(registry); + } + + protected void copyFrom(RuntimeEndpointReferenceImpl copy) { + this.xml = copy.xml; + + this.component = copy.component; + this.reference = copy.reference; + this.interfaceContract = copy.interfaceContract; + this.referenceInterfaceContract = copy.referenceInterfaceContract; + this.callbackEndpoint = copy.callbackEndpoint; + this.targetEndpoint = copy.targetEndpoint; + + this.binding = copy.binding; + this.bindingInterfaceContract = copy.interfaceContract; + this.bindingInvocationChain = copy.bindingInvocationChain; + + this.requiredIntents = copy.requiredIntents; + this.policySets = copy.policySets; + + this.uri = copy.uri; + this.unresolved = copy.unresolved; + this.status = copy.status; + + this.chains = copy.chains; + this.invocationChainMap = copy.invocationChainMap; + this.bindingProvider = copy.bindingProvider; + this.policyProviders = copy.policyProviders; + + if (this.compositeContext == null && copy.compositeContext != null) { + bind(copy.compositeContext); + } + } + + public void bind(CompositeContext compositeContext) { + this.compositeContext = compositeContext; + bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry()); + } + + public void bind(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry) { + if (compositeContext == null) { + compositeContext = new CompositeContext(registry, endpointRegistry); + } + this.registry = registry; + this.endpointRegistry = endpointRegistry; + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + this.wireProcessor = + new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); + + this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class); + this.invoker = new RuntimeInvoker(registry, this); + + this.phaseManager = utilities.getUtility(PhaseManager.class); + this.serializer = utilities.getUtility(EndpointSerializer.class); + this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + this.contractBuilder = builders.getContractBuilder(); + } + + public synchronized List<InvocationChain> getInvocationChains() { + if (chains == null) { + initInvocationChains(); + } + return chains; + } + + public synchronized InvocationChain getBindingInvocationChain() { + if (bindingInvocationChain == null) { + bindingInvocationChain = new InvocationChainImpl(null, null, true, phaseManager, isAsyncInvocation()); + initReferenceBindingInvocationChains(); + } + return bindingInvocationChain; + } + + public InvocationChain getInvocationChain(Operation operation) { + InvocationChain cached = invocationChainMap.get(operation); + if (cached == null) { + for (InvocationChain chain : getInvocationChains()) { + Operation op = chain.getSourceOperation(); + + // We used to check compatibility here but this is now validated when the + // chain is created. As the chain operations are the real interface types + // they may be incompatible just because they are described in different + // IDLs + if (operation.getName().equals(op.getName())) { + invocationChainMap.put(operation, chain); + return chain; + } + } + invocationChainMap.put(operation, null); + return null; + } else { + return cached; + } + } + + public Message invoke(Message msg) { + return invoker.invoke(msg); + } + + public Object invoke(Operation operation, Object[] args) throws InvocationTargetException { + return invoker.invoke(operation, args); + } + + public Message invoke(Operation operation, Message msg) { + return invoker.invoke(operation, msg); + } + + public void invokeAsync(Operation operation, Message msg){ + msg.setOperation(operation); + invoker.invokeAsync(msg); + } + + public void invokeAsync(Message msg){ + invoker.invokeAsync(msg); + } + + public void invokeAsyncResponse(Message msg){ + // If there is a Binding Chain, invoke it first... + InvocationChain chain = this.getBindingInvocationChain(); + if( chain != null ) { + Invoker tailInvoker = chain.getTailInvoker(); + if (tailInvoker != null) { + ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg); + } // end if + } // end if + + chain = this.getInvocationChain(msg.getOperation()); + Invoker tailInvoker = chain.getTailInvoker(); + ((InvokerAsyncResponse)tailInvoker).invokeAsyncResponse(msg); + } // end method invokeAsyncResponse + + /** + * Navigate the component/componentType inheritence chain to find the leaf contract + * @param contract + * @return + */ + private Contract getLeafContract(Contract contract) { + Contract prev = null; + Contract current = contract; + while (current != null) { + prev = current; + if (current instanceof ComponentReference) { + current = ((ComponentReference)current).getReference(); + } else if (current instanceof CompositeReference) { + current = ((CompositeReference)current).getPromotedReferences().get(0); + } else if (current instanceof ComponentService) { + current = ((ComponentService)current).getService(); + } else if (current instanceof CompositeService) { + current = ((CompositeService)current).getPromotedService(); + } else { + break; + } + if (current == null) { + return prev; + } + } + return current; + } + + /** + * Initialize the invocation chains + */ + private void initInvocationChains() { + InterfaceContract sourceContract = getComponentTypeReferenceInterfaceContract(); + // TODO - EPR why is this looking at the component types. The endpoint reference should have the right interface contract by this time + //InterfaceContract sourceContract = getLeafInterfaceContract(endpointReference); + + // It's the reference wire + resolveEndpointReference(); + + InterfaceContract targetContract = getBindingInterfaceContract(); + // TODO - EPR why is this looking at the component types. The endpoint should have the right interface contract by this time + //InterfaceContract targetContract = getLeafInterfaceContract(endpoint); + + if (sourceContract == null && targetContract != null) { + // TODO: until the web component introspection is brought up + try { + sourceContract = (InterfaceContract)targetContract.clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e); + } + } + + validateReferenceInterfaceCompatibility(); + + List<InvocationChain> chainList = new ArrayList<InvocationChain>(); + if(sourceContract != null && targetContract != null) { + RuntimeComponentReference reference = (RuntimeComponentReference)getReference(); + for (Operation operation : sourceContract.getInterface().getOperations()) { + Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation); + if (targetOperation == null) { + throw new ServiceRuntimeException("No matching operation for " + operation.getName() + + " is found in reference " + + getComponent().getURI() + + "#" + + reference.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true, phaseManager, isAsyncInvocation()); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(chain); + } + chainList.add(chain); + addReferenceBindingInterceptor(chain, operation); + } + } + + // Set the chains until it's fully populated. If we initialize too early, any exception could + // leave this endpoint reference in a wrong state with an empty chain. + chains = chainList; + wireProcessor.process(this); + + if (isAsyncInvocation()){ + // fix up all of the operation chain response paths + // to point back to the implementation provided + // async response handler + ImplementationProvider implementationProvider = ((RuntimeComponent)getComponent()).getImplementationProvider(); + if (implementationProvider instanceof ImplementationAsyncProvider){ + for (InvocationChain chain : getInvocationChains()){ + InvokerAsyncResponse asyncResponseInvoker = ((ImplementationAsyncProvider)implementationProvider).createAsyncResponseInvoker(chain.getSourceOperation()); + if (chain.getHeadInvoker() instanceof InterceptorAsync){ + ((InterceptorAsync)chain.getHeadInvoker()).setPrevious(asyncResponseInvoker); + } else { + //TODO - throw error once the old async code is removed + } + } + } + } + } + + /** + * Check that endpoint reference has compatible interface at the component and binding ends. + * The user can specify the interfaces at both ends so there is a danger that they won't be compatible. + * There is checking in the activator but of course endpoint references may not have a binding assigned + * until final resolution. + */ + public void validateReferenceInterfaceCompatibility() { + + InterfaceContract referenceContract = getComponentReferenceInterfaceContract(); + InterfaceContract bindingContract = getBindingInterfaceContract(); + + if ((referenceContract != null) && + (bindingContract != null)){ + + boolean bindingHasCallback = bindingContract.getCallbackInterface() != null; + + try { + // Use the normalized contract if the interface types are different or if + // a normalized contract has been previously generate, for example, by virtue + // of finding a JAXWS annotation on a Java class that references a WSDL file + if (referenceContract.getClass() != bindingContract.getClass() || + referenceContract.getNormalizedWSDLContract() != null || + bindingContract.getNormalizedWSDLContract() != null) { + interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(referenceContract), + getGeneratedWSDLContract(bindingContract), + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } else { + interfaceContractMapper.checkCompatibility(referenceContract, + bindingContract, + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } + } catch (Exception ex){ + throw new ServiceRuntimeException("Component " + + this.getComponent().getName() + + " Reference " + + getReference().getName() + + " interface is incompatible with the interface of the reference binding " + + getBinding().getName() + + " - " + + ex.getMessage() + + " - [" + this.toString() + "]"); + } + } + } + + /** + * This code used to be in the activator but has moved here as + * the endpoint reference may not now be resolved until the wire + * is first used + */ + private void resolveEndpointReference() { + resolve(); + + eprBinder.bindRunTime(endpointRegistry, this); + + // start the binding provider + final ReferenceBindingProvider bindingProvider = getBindingProvider(); + + if (bindingProvider != null) { + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.start(); + return null; + } + }); + } + for (PolicyProvider policyProvider : getPolicyProviders()) { + policyProvider.start(); + } + + started = true; + // InterfaceContract bindingContract = getBindingInterfaceContract(); + // endpoint.setInterfaceContract(bindingContract); + } + + private void initReferenceBindingInvocationChains() { + + // add the binding interceptors to the reference binding wire + ReferenceBindingProvider provider = getBindingProvider(); + if ((provider != null) && (provider instanceof EndpointReferenceProvider)) { + ((EndpointReferenceProvider)provider).configure(); + } + + // add the policy interceptors to the service binding wire + // find out which policies are active + for (PolicyProvider p : getPolicyProviders()) { + Interceptor interceptor = p.createBindingInterceptor(); + if (interceptor != null) { + bindingInvocationChain.addInterceptor(interceptor); + } + } + } + + public void rebuild() { + // TODO - can we use the idea of setTarget to rebuild the wire? + // used at the moment by binding.sca when it resets the + // source interface contract for local wires + this.chains = null; + + if (getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED){ + setStatus(EndpointReference.Status.NOT_CONFIGURED); + } + + // TODO - cheating here as I fixed the RuntimeComponentService code + // to call this when it resets the interface contract + //endpointReference.setInterfaceContract(epr.getInterfaceContract()); + } + + /** + * Add the interceptor for a reference binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addReferenceBindingInterceptor(InvocationChain chain, Operation operation) { + ReferenceBindingProvider provider = getBindingProvider(); + if (provider != null) { + Invoker invoker = provider.createInvoker(operation); + if (invoker != null) { + chain.addInvoker(invoker); + } + } + List<PolicyProvider> pps = getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createBindingInterceptor(); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + } + } + } + + /** + * Add a non-blocking interceptor if the reference binding needs it + * + * @param reference + * @param binding + * @param chain + */ + private void addNonBlockingInterceptor(InvocationChain chain) { + ReferenceBindingProvider provider = getBindingProvider(); + if (provider != null) { + boolean supportsOneWayInvocation = provider.supportsOneWayInvocation(); + if (!supportsOneWayInvocation) { + chain.addInterceptor(Phase.REFERENCE, new NonBlockingInterceptor(workScheduler)); + } + } + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeEndpointReferenceImpl copy = (RuntimeEndpointReferenceImpl)super.clone(); + copy.invoker = new RuntimeInvoker(registry, copy); + return copy; + } + + public boolean isOutOfDate() { + resolve(); + return eprBinder.isOutOfDate(endpointRegistry, this); + } + + public synchronized ReferenceBindingProvider getBindingProvider() { + resolve(); + // For the case that binding.sca is implemented by another binding + if (binding == null) { + return null; + } + if (bindingProvider == null) { + BindingProviderFactory factory = + (BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass()); + if (factory == null) { + throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding() + .getType()); + } + this.bindingProvider = factory.createReferenceBindingProvider(this); + } + return bindingProvider; + } + + public void setBindingProvider(ReferenceBindingProvider bindingProvider) { + this.bindingProvider = bindingProvider; + } + + public synchronized List<PolicyProvider> getPolicyProviders() { + resolve(); + if (policyProviders == null) { + policyProviders = new ArrayList<PolicyProvider>(); + for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) { + PolicyProvider provider = factory.createReferencePolicyProvider(this); + if (provider != null) { + policyProviders.add(provider); + } + } + } + return policyProviders; + } + + public void unbind() { + bindingInvocationChain = null; + chains = null; + bindingProvider = null; + policyProviders = null; + invocationChainMap.clear(); + } + + public Contract getContract() { + return getReference(); + } + + public CompositeContext getCompositeContext() { + return compositeContext; + } + + public InterfaceContract getBindingInterfaceContract() { + resolve(); + if (bindingInterfaceContract != null) { + return bindingInterfaceContract; + } + ReferenceBindingProvider provider = getBindingProvider(); + if (provider != null) { + bindingInterfaceContract = provider.getBindingInterfaceContract(); + } + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentReferenceInterfaceContract(); + } + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentTypeReferenceInterfaceContract(); + } + return bindingInterfaceContract; + } + + public InterfaceContract getComponentTypeReferenceInterfaceContract() { + resolve(); + if (referenceInterfaceContract != null) { + return referenceInterfaceContract; + } + if (reference == null) { + return getComponentReferenceInterfaceContract(); + } + referenceInterfaceContract = getLeafContract(reference).getInterfaceContract(); + if (referenceInterfaceContract == null) { + referenceInterfaceContract = getComponentReferenceInterfaceContract(); + } + return referenceInterfaceContract; + } + + @Override + protected synchronized void resolve() { + if (xml != null && component == null) { + if (compositeContext == null) { + compositeContext = CompositeContext.getCurrentCompositeContext(); + if (compositeContext != null) { + bind(compositeContext); + } + } + RuntimeEndpointReferenceImpl epr = (RuntimeEndpointReferenceImpl)serializer.readEndpointReference(xml); + copyFrom(epr); + } + super.resolve(); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.uri = in.readUTF(); + this.xml = in.readUTF(); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(getURI()); + if (serializer == null && xml != null) { + out.writeUTF(xml); + } else { + if (serializer != null) { + out.writeUTF(serializer.write(this)); + } else { + throw new IllegalStateException("No serializer is configured"); + } + } + } + + public boolean isStarted() { + return started; + } + + public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) { + + if ( interfaceContract.getNormalizedWSDLContract() == null){ + if (getComponentReferenceInterfaceContract() instanceof JavaInterfaceContract){ + if (contractBuilder == null){ + throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString()); + } + contractBuilder.build(interfaceContract, null); + } + } + + return interfaceContract.getNormalizedWSDLContract(); + } + + public void createAsyncCallbackEndpoint(){ + CompositeContext compositeContext = getCompositeContext(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + RuntimeAssemblyFactory assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + + RuntimeEndpoint endpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint(); + endpoint.bind(compositeContext); + endpoint.setComponent(getComponent()); + + // Create pseudo-service + ComponentService service = assemblyFactory.createComponentService(); + JavaInterfaceFactory javaInterfaceFactory = + (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class); + JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + try { + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseHandler.class)); + } catch (InvalidInterfaceException e1) { + // Nothing to do here - will not happen + } // end try + + service.setInterfaceContract(interfaceContract); + + String serviceName = getReference().getName() + "_asyncCallback"; + service.setName(serviceName); + service.getEndpoints().add(endpoint); + service.setForCallback(true); + endpoint.setService(service); + + // Set pseudo-service onto the component + getComponent().getServices().add(service); + + // if the reference has a WSDL contract reset the response endpoint to be WSDL also + InterfaceContract referenceInterfaceContract = getComponentTypeReferenceInterfaceContract(); + if (referenceInterfaceContract instanceof WSDLInterfaceContract){ + WSDLInterfaceContract wsdlInterfaceContract = (WSDLInterfaceContract)endpoint.getGeneratedWSDLContract(interfaceContract); + service.setInterfaceContract(wsdlInterfaceContract); + } + + // Create a binding + // Mike had to go via the XML but I don't remember why + Binding binding = null; + try { + binding = (Binding)getBinding().clone(); + } catch (Exception ex){ + // + } + String callbackURI = "/" + component.getName() + "/" + service.getName(); + binding.setURI(callbackURI); + + BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + BindingBuilder builder = builders.getBindingBuilder(binding.getType()); + if (builder != null) { + org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry); + builder.build(component, service, binding, builderContext, true); + } // end if + + endpoint.setBinding(binding); + + // Need to establish policies here (binding has some...) + endpoint.getRequiredIntents().addAll(getRequiredIntents()); + endpoint.getPolicySets().addAll(getPolicySets()); + String epURI = getComponent().getName() + "#service-binding(" + serviceName + "/" + serviceName + ")"; + endpoint.setURI(epURI); + endpoint.setUnresolved(false); + + setCallbackEndpoint(endpoint); + } +} |