/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.sca.node.impl; import static java.lang.System.currentTimeMillis; import static org.apache.tuscany.sca.definitions.util.SCADefinitionsUtil.aggregateSCADefinitions; import static org.apache.tuscany.sca.node.impl.NodeUtil.contribution; import static org.apache.tuscany.sca.node.impl.NodeUtil.createURI; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import org.apache.tuscany.sca.assembly.AssemblyFactory; import org.apache.tuscany.sca.assembly.Component; import org.apache.tuscany.sca.assembly.ComponentService; import org.apache.tuscany.sca.assembly.Composite; import org.apache.tuscany.sca.assembly.CompositeService; import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; import org.apache.tuscany.sca.assembly.builder.CompositeBuilderExtensionPoint; import org.apache.tuscany.sca.contribution.Artifact; import org.apache.tuscany.sca.contribution.Contribution; import org.apache.tuscany.sca.contribution.ContributionFactory; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; import org.apache.tuscany.sca.contribution.resolver.DefaultModelResolver; import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver; import org.apache.tuscany.sca.contribution.resolver.ModelResolver; import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; import org.apache.tuscany.sca.contribution.service.ContributionResolveException; import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; import org.apache.tuscany.sca.core.ModuleActivator; import org.apache.tuscany.sca.core.ModuleActivatorExtensionPoint; import org.apache.tuscany.sca.core.UtilityExtensionPoint; import org.apache.tuscany.sca.core.assembly.ActivationException; import org.apache.tuscany.sca.core.assembly.CompositeActivator; import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; import org.apache.tuscany.sca.core.invocation.ProxyFactory; import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; import org.apache.tuscany.sca.definitions.SCADefinitions; import org.apache.tuscany.sca.definitions.impl.SCADefinitionsImpl; import org.apache.tuscany.sca.implementation.node.ConfiguredNodeImplementation; import org.apache.tuscany.sca.implementation.node.NodeImplementationFactory; import org.apache.tuscany.sca.monitor.Monitor; import org.apache.tuscany.sca.monitor.MonitorFactory; import org.apache.tuscany.sca.monitor.Problem; import org.apache.tuscany.sca.monitor.Problem.Severity; import org.apache.tuscany.sca.node.Client; import org.apache.tuscany.sca.node.Node; import org.apache.tuscany.sca.policy.Intent; import org.apache.tuscany.sca.policy.IntentAttachPointType; import org.apache.tuscany.sca.policy.PolicySet; import org.apache.tuscany.sca.provider.SCADefinitionsProvider; import org.apache.tuscany.sca.provider.SCADefinitionsProviderException; import org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.apache.tuscany.sca.runtime.RuntimeComponentContext; import org.apache.tuscany.sca.work.WorkScheduler; import org.apache.tuscany.sca.workspace.Workspace; import org.apache.tuscany.sca.workspace.WorkspaceFactory; import org.apache.tuscany.sca.workspace.builder.ContributionBuilder; import org.apache.tuscany.sca.workspace.builder.ContributionBuilderExtensionPoint; import org.osoa.sca.CallableReference; import org.osoa.sca.ServiceReference; import org.osoa.sca.ServiceRuntimeException; /** * Represents an SCA runtime node. * * @version $Rev$ $Date$ */ public class NodeImpl implements Node, Client { private static final Logger logger = Logger.getLogger(NodeImpl.class.getName()); // The node configuration name, used for logging private String configurationName; // The composite loaded into this node private Composite composite; private ExtensionPointRegistry extensionPoints; private Monitor monitor; private URLArtifactProcessor contributionProcessor; private ModelResolverExtensionPoint modelResolvers; private FactoryExtensionPoint modelFactories; private WorkspaceFactory workspaceFactory; private ContributionFactory contributionFactory; private AssemblyFactory assemblyFactory; private XMLInputFactory inputFactory; private ContributionBuilder contributionDependencyBuilder; private CompositeBuilder compositeBuilder; private StAXArtifactProcessorExtensionPoint xmlProcessors; private StAXArtifactProcessor compositeProcessor; private ProxyFactory proxyFactory; private List moduleActivators = new ArrayList(); private CompositeActivator compositeActivator; private WorkScheduler workScheduler; private SCADefinitions systemDefinitions; /** * Constructs a new SCA node. * * @param configurationURI the URI of the node configuration information. */ NodeImpl(String configurationURI) { configurationName = configurationURI; logger.log(Level.INFO, "Creating node: " + configurationName); try { // Initialize the runtime init(); // Read the node configuration feed StAXArtifactProcessor configurationProcessor = xmlProcessors.getProcessor(ConfiguredNodeImplementation.class); URL configurationURL = new URL(configurationURI); InputStream is = configurationURL.openStream(); XMLStreamReader reader = inputFactory.createXMLStreamReader(is); reader.nextTag(); ConfiguredNodeImplementation configuration = configurationProcessor.read(reader); is.close(); // Resolve contribution URLs for (Contribution contribution : configuration.getContributions()) { URL contributionURL = new URL(configurationURL, contribution.getLocation()); contribution.setLocation(contributionURL.toString()); } // Resolve composite URL URL compositeURL = new URL(configurationURL, configuration.getComposite().getURI()); configuration.getComposite().setURI(compositeURL.toString()); // Configure the node configureNode(configuration); } catch (Exception e) { throw new ServiceRuntimeException(e); } } /** * Constructs a new SCA node. * * @param compositeURI * @param contributions */ NodeImpl(String compositeURI, org.apache.tuscany.sca.node.Contribution[] contributions) { configurationName = compositeURI; logger.log(Level.INFO, "Creating node: " + configurationName); try { // Initialize the runtime init(); // Create a node configuration NodeImplementationFactory nodeImplementationFactory = modelFactories.getFactory(NodeImplementationFactory.class); ConfiguredNodeImplementation configuration = nodeImplementationFactory.createConfiguredNodeImplementation(); if (compositeURI != null) { Composite composite = assemblyFactory.createComposite(); composite.setURI(compositeURI); composite.setUnresolved(true); configuration.setComposite(composite); } // Create contribution models for (org.apache.tuscany.sca.node.Contribution c : contributions) { Contribution contribution = contribution(contributionFactory, c); configuration.getContributions().add(contribution); } // Configure the node configureNode(configuration); } catch (Exception e) { throw new ServiceRuntimeException(e); } } /** * Constructs a new SCA node. * * @param compositeURI * @param compositeContent * @param contributions */ NodeImpl(String compositeURI, String compositeContent, org.apache.tuscany.sca.node.Contribution[] contributions) { configurationName = compositeURI; logger.log(Level.INFO, "Creating node: " + configurationName); try { // Initialize the runtime init(); // Create a node configuration NodeImplementationFactory nodeImplementationFactory = modelFactories.getFactory(NodeImplementationFactory.class); ConfiguredNodeImplementation configuration = nodeImplementationFactory.createConfiguredNodeImplementation(); // Read the composite model logger.log(Level.INFO, "Loading composite: " + compositeURI); XMLStreamReader reader = inputFactory.createXMLStreamReader(new ByteArrayInputStream(compositeContent.getBytes("UTF-8"))); reader.nextTag(); // Read the composite model composite = (Composite)compositeProcessor.read(reader); if (composite != null) { composite.setURI(compositeURI); } analyzeProblems(); configuration.setComposite(composite); // Create contribution models for (org.apache.tuscany.sca.node.Contribution c : contributions) { Contribution contribution = contribution(contributionFactory, c); configuration.getContributions().add(contribution); } // Configure the node configureNode(configuration); } catch (Exception e) { throw new ServiceRuntimeException(e); } } private void init() { long start = currentTimeMillis(); // Create extension point registry extensionPoints = new DefaultExtensionPointRegistry(); // Create a monitor UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class); monitor = monitorFactory.createMonitor(); // Initialize the Tuscany module activators ModuleActivatorExtensionPoint activators = extensionPoints.getExtensionPoint(ModuleActivatorExtensionPoint.class); for (ModuleActivator moduleActivator: activators.getModuleActivators()) { moduleActivator.start(extensionPoints); moduleActivators.add(moduleActivator); } // Get XML input/output factories modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); inputFactory = modelFactories.getFactory(XMLInputFactory.class); // Get contribution workspace and assembly model factories contributionFactory = modelFactories.getFactory(ContributionFactory.class); workspaceFactory = modelFactories.getFactory(WorkspaceFactory.class); assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); // Use the runtime-enabled assembly factory assemblyFactory = new RuntimeAssemblyFactory(); modelFactories.addFactory(assemblyFactory); // Create XML artifact processors xmlProcessors = extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); compositeProcessor = xmlProcessors.getProcessor(Composite.class); // Create contribution content processor URLArtifactProcessorExtensionPoint docProcessorExtensions = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); contributionProcessor = docProcessorExtensions.getProcessor(Contribution.class); // Get the model resolvers modelResolvers = extensionPoints.getExtensionPoint(ModelResolverExtensionPoint.class); // Get a contribution dependency builder ContributionBuilderExtensionPoint contributionBuilders = extensionPoints.getExtensionPoint(ContributionBuilderExtensionPoint.class); contributionDependencyBuilder = contributionBuilders.getContributionBuilder("org.apache.tuscany.sca.workspace.builder.ContributionDependencyBuilder"); // Get composite builders CompositeBuilderExtensionPoint compositeBuilders = extensionPoints.getExtensionPoint(CompositeBuilderExtensionPoint.class); compositeBuilder = compositeBuilders.getCompositeBuilder("org.apache.tuscany.sca.assembly.builder.CompositeBuilder"); // Initialize runtime // Get proxy factory ProxyFactoryExtensionPoint proxyFactories = extensionPoints.getExtensionPoint(ProxyFactoryExtensionPoint.class); proxyFactory = new ExtensibleProxyFactory(proxyFactories); // Get the composite activator compositeActivator = utilities.getUtility(CompositeActivator.class); workScheduler = utilities.getUtility(WorkScheduler.class); // This is not right, the aggregate algorithm is not right, adding policies to // a resolver like that is not correct as these policies won't be seen by the resolvers // used by the contributions, and we shouldn't have to use the doc processor to do // the resolution, so commenting out for now as it's not critical to get working in // the Equinox environment initially // // Load the system definitions.xml // SCADefinitionsProviderExtensionPoint definitionsProviders = extensionPoints.getExtensionPoint(SCADefinitionsProviderExtensionPoint.class); // systemDefinitions = new SCADefinitionsImpl(); // try { // for (SCADefinitionsProvider definitionsProvider : definitionsProviders.getSCADefinitionsProviders()) { // aggregateSCADefinitions(definitionsProvider.getSCADefinition(), systemDefinitions); // } // } catch (SCADefinitionsProviderException e) { // throw new IllegalStateException(e); // } // // // Configure a resolver for the system definitions // ModelResolver definitionsResolver = new DefaultModelResolver(); // for (Intent intent : systemDefinitions.getPolicyIntents()) { // definitionsResolver.addModel(intent); // } // for (PolicySet policySet : systemDefinitions.getPolicySets()) { // definitionsResolver.addModel(policySet); // } // for (IntentAttachPointType bindingType : systemDefinitions.getBindingTypes()) { // definitionsResolver.addModel(bindingType); // } // for (IntentAttachPointType implementationType : systemDefinitions.getImplementationTypes()) { // definitionsResolver.addModel(implementationType); // } // // // Now that all system sca definitions have been read, let's resolve them // URLArtifactProcessorExtensionPoint documentProcessors = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); // URLArtifactProcessor definitionsProcessor = documentProcessors.getProcessor(SCADefinitions.class); // try { // definitionsProcessor.resolve(systemDefinitions, definitionsResolver); // } catch (ContributionResolveException e) { // throw new IllegalStateException(e); // } if (logger.isLoggable(Level.FINE)) { long end = currentTimeMillis(); logger.fine("The tuscany runtime started in " + (end - start) + " ms."); } } private void configureNode(ConfiguredNodeImplementation configuration) throws Exception { // Create workspace model Workspace workspace = workspaceFactory.createWorkspace(); workspace.setModelResolver(new ExtensibleModelResolver(workspace, modelResolvers, modelFactories)); // Load the specified contributions for (Contribution c : configuration.getContributions()) { URI contributionURI = URI.create(c.getURI()); URI uri = createURI(c.getLocation()); if (uri.getScheme() == null) { uri = new File(c.getLocation()).toURI(); } URL contributionURL = uri.toURL(); // Load the contribution logger.log(Level.INFO, "Loading contribution: " + contributionURL); Contribution contribution = contributionProcessor.read(null, contributionURI, contributionURL); workspace.getContributions().add(contribution); analyzeProblems(); } // Build the contribution dependencies Set resolved = new HashSet(); for (Contribution contribution: workspace.getContributions()) { contributionDependencyBuilder.build(contribution, workspace, monitor); // Resolve contributions for (Contribution dependency: contribution.getDependencies()) { if (!resolved.contains(dependency)) { resolved.add(dependency); contributionProcessor.resolve(dependency, workspace.getModelResolver()); } } } composite = configuration.getComposite(); // Find the composite in the given contributions boolean found = false; Artifact compositeFile = contributionFactory.createArtifact(); compositeFile.setUnresolved(true); compositeFile.setURI(composite.getURI()); for (Contribution contribution: workspace.getContributions()) { ModelResolver resolver = contribution.getModelResolver(); Artifact resolvedArtifact = resolver.resolveModel(Artifact.class, compositeFile); if (!resolvedArtifact.isUnresolved() && resolvedArtifact.getModel() instanceof Composite) { if (!composite.isUnresolved()) { // The composite content was passed into the node and read into a composite model, // don't use the composite found in the contribution, use that composite, but just resolve // it within the context of the contribution compositeProcessor.resolve(composite, resolver); } else { // Use the resolved composite we've found in the contribution composite = (Composite)resolvedArtifact.getModel(); } found = true; break; } } if (!found) { throw new IllegalArgumentException("Composite not found: " + composite.getURI()); } // Build an aggregated SCA definitions model SCADefinitions definitions = systemDefinitions; //definitions = new SCADefinitionsImpl(); //for (SCADefinitions definition : ((List)policyDefinitions)) { // SCADefinitionsUtil.aggregateSCADefinitions(definition, definitions); //} // Build the composite and wire the components included in it compositeBuilder.build(composite, definitions, monitor); analyzeProblems(); // Create a top level composite to host our composite // This is temporary to make the activator happy Composite tempComposite = assemblyFactory.createComposite(); tempComposite.setName(new QName("http://tempuri.org", "temp")); tempComposite.setURI("http://tempuri.org"); // Include the node composite in the top-level composite tempComposite.getIncludes().add(composite); // Set the top level composite on the composite activator as // logic in callable reference resolution relies on this being // available compositeActivator.setDomainComposite(tempComposite); } public void start() { logger.log(Level.INFO, "Starting node: " + configurationName); try { // Activate the composite compositeActivator.activate(composite); // Start the composite compositeActivator.start(composite); } catch (ActivationException e) { throw new IllegalStateException(e); } } public void stop() { logger.log(Level.INFO, "Stopping node: " + configurationName); try { // Stop the composite compositeActivator.stop(composite); // Deactivate the composite compositeActivator.deactivate(composite); } catch (ActivationException e) { throw new IllegalStateException(e); } } public void destroy() { // Stop the runtime modules for (ModuleActivator moduleActivator: moduleActivators) { moduleActivator.stop(extensionPoints); } // Stop and destroy the work manager workScheduler.destroy(); } public > R cast(B target) throws IllegalArgumentException { return (R)proxyFactory.cast(target); } public B getService(Class businessInterface, String serviceName) { ServiceReference serviceReference = getServiceReference(businessInterface, serviceName); if (serviceReference == null) { throw new ServiceRuntimeException("Service not found: " + serviceName); } return serviceReference.getService(); } public ServiceReference getServiceReference(Class businessInterface, String name) { // Extract the component name String componentName; String serviceName; int i = name.indexOf('/'); if (i != -1) { componentName = name.substring(0, i); serviceName = name.substring(i + 1); } else { componentName = name; serviceName = null; } // Lookup the component Component component = null; for (Component compositeComponent : composite.getComponents()) { if (compositeComponent.getName().equals(componentName)) { component = compositeComponent; } } if (component == null) { throw new ServiceRuntimeException("The service " + name + " has not been contributed to the domain"); } RuntimeComponentContext componentContext = null; // If the component is a composite, then we need to find the // non-composite component that provides the requested service if (component.getImplementation() instanceof Composite) { for (ComponentService componentService : component.getServices()) { if (serviceName == null || serviceName.equals(componentService.getName())) { CompositeService compositeService = (CompositeService)componentService.getService(); if (compositeService != null) { if (serviceName != null) { serviceName = "$promoted$" + component.getName() + "$slash$" + serviceName; } componentContext = ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext(); return componentContext.createSelfReference(businessInterface, compositeService .getPromotedService()); } break; } } // No matching service found throw new ServiceRuntimeException("Composite service not found: " + name); } else { componentContext = ((RuntimeComponent)component).getComponentContext(); if (serviceName != null) { return componentContext.createSelfReference(businessInterface, serviceName); } else { return componentContext.createSelfReference(businessInterface); } } } /** * Analyze problems reported by the artifact processors and builders. * * @throws Exception */ private void analyzeProblems() throws Exception { for (Problem problem : monitor.getProblems()) { if ((problem.getSeverity() == Severity.ERROR) && (!problem.getMessageId().equals("SchemaError"))) { if (problem.getCause() != null) { throw problem.getCause(); } else { throw new ServiceRuntimeException(problem.toString()); } } } } }