/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.sca.bc; import static java.lang.System.currentTimeMillis; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; 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.client.impl.SCAClientImpl; 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.DefaultImport; import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; import org.apache.tuscany.sca.contribution.processor.ExtendedURLArtifactProcessor; 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.processor.ValidationSchemaExtensionPoint; 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.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.Definitions; import org.apache.tuscany.sca.definitions.DefinitionsFactory; import org.apache.tuscany.sca.definitions.util.DefinitionsUtil; import org.apache.tuscany.sca.definitions.xml.DefinitionsExtensionPoint; 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.ContributionLocationHelper; import org.apache.tuscany.sca.node.Node; import org.apache.tuscany.sca.provider.DefinitionsProvider; import org.apache.tuscany.sca.provider.DefinitionsProviderException; import org.apache.tuscany.sca.provider.DefinitionsProviderExtensionPoint; 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.oasisopen.sca.CallableReference; import org.oasisopen.sca.NoSuchDomainException; import org.oasisopen.sca.NoSuchServiceException; import org.oasisopen.sca.ServiceReference; import org.oasisopen.sca.ServiceRuntimeException; import org.oasisopen.sca.client.SCAClient; /** * Represents an SCA runtime node. * * @version $Rev$ $Date$ */ public class ContributionProcessorImpl { private static final String SCA11_TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.1"; private static final Logger logger = Logger.getLogger(ContributionProcessorImpl.class.getName()); // The node configuration name, used for logging private String configurationName; // The composite loaded into this node private Composite composite; private boolean useDeploymentComposite; private ExtensionPointRegistry extensionPoints; private Monitor monitor; private ExtendedURLArtifactProcessor 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 CompositeBuilder endpointReferenceBuilder; private StAXArtifactProcessorExtensionPoint xmlProcessors; private StAXArtifactProcessor compositeProcessor; private ProxyFactory proxyFactory; private List moduleActivators = new ArrayList(); private CompositeActivator compositeActivator; private WorkScheduler workScheduler; private Contribution systemContribution; private Definitions systemDefinitions; // Added MJE 28/04/2009 private URLArtifactProcessor compositeDocumentProcessor; /** * Constructs a new SCA node. * * @param compositeURI * @param contributions */ ContributionProcessorImpl(org.apache.tuscany.sca.node.Contribution[] contributions) { configurationName = "temp"; logger.log(Level.INFO, "Creating contribution processor: " + configurationName); try { // Initialize the runtime init(); // Create a node configuration NodeImplementationFactory nodeImplementationFactory = modelFactories.getFactory(NodeImplementationFactory.class); ConfiguredNodeImplementation configuration = nodeImplementationFactory.createConfiguredNodeImplementation(); // 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); } } static Contribution contribution(ContributionFactory contributionFactory, org.apache.tuscany.sca.node.Contribution c) { Contribution contribution = contributionFactory.createContribution(); contribution.setURI(c.getURI()); contribution.setLocation(c.getLocation()); contribution.setUnresolved(true); return contribution; } private static String getSystemProperty(final String name) { return AccessController.doPrivileged(new PrivilegedAction() { public String run() { return System.getProperty(name); } }); } static URI createURI(String uri) { if (uri.indexOf(' ') != -1) { uri = uri.replace(" ", "%20"); } return URI.create(uri); } private void init() { long start = currentTimeMillis(); // Create extension point registry extensionPoints = new DefaultExtensionPointRegistry(); // Enable schema validation only of the logger level is FINE or higher ValidationSchemaExtensionPoint schemas = extensionPoints.getExtensionPoint(ValidationSchemaExtensionPoint.class); if (schemas != null) { String enabled = getSystemProperty(ValidationSchemaExtensionPoint.class.getName() + ".enabled"); if (enabled == null) { enabled = "true"; } boolean debug = logger.isLoggable(Level.FINE); schemas.setEnabled("true".equals(enabled) || debug); } // Use the runtime-enabled assembly factory modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); assemblyFactory = new RuntimeAssemblyFactory(); modelFactories.addFactory(assemblyFactory); // 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()) { try { moduleActivator.start(extensionPoints); moduleActivators.add(moduleActivator); } catch (Throwable e) { // Ignore the failing module for now logger.log(Level.SEVERE, e.getMessage(), e); } } // Get XML input/output factories inputFactory = modelFactories.getFactory(XMLInputFactory.class); // Get contribution workspace and assembly model factories contributionFactory = modelFactories.getFactory(ContributionFactory.class); workspaceFactory = modelFactories.getFactory(WorkspaceFactory.class); // 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 = (ExtendedURLArtifactProcessor) docProcessorExtensions.getProcessor(Contribution.class); // Added MJE 28/04/2009 // Create Composite Document processor compositeDocumentProcessor = docProcessorExtensions.getProcessor(Composite.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"); // Get endpoint builders // TODO - new extension point? endpointReferenceBuilder = compositeBuilders.getCompositeBuilder("org.apache.tuscany.sca.endpoint.impl.EndpointReferenceBuilderImpl"); // 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); DefinitionsFactory definitionsFactory = modelFactories.getFactory(DefinitionsFactory.class); systemDefinitions = definitionsFactory.createDefinitions(); DefinitionsExtensionPoint definitionsExtensionPoint = extensionPoints.getExtensionPoint(DefinitionsExtensionPoint.class); for (Definitions defs : definitionsExtensionPoint.getDefinitions()) { DefinitionsUtil.aggregate(systemDefinitions, defs); } // Load the system definitions.xml from all of the loaded extension points DefinitionsProviderExtensionPoint definitionsProviders = extensionPoints.getExtensionPoint(DefinitionsProviderExtensionPoint.class); // aggregate all the definitions into a single definitions model try { for (DefinitionsProvider definitionsProvider : definitionsProviders.getDefinitionsProviders()) { DefinitionsUtil.aggregate(definitionsProvider.getDefinitions(), systemDefinitions); } } catch (DefinitionsProviderException e) { throw new IllegalStateException(e); } // create a system contribution to hold the definitions. The contribution // will be extended later with definitions from application contributions systemContribution = contributionFactory.createContribution(); systemContribution.setURI("http://tuscany.apache.org/SystemContribution"); systemContribution.setLocation("http://tuscany.apache.org/SystemContribution"); ModelResolver modelResolver = new ExtensibleModelResolver(systemContribution, modelResolvers, modelFactories); systemContribution.setModelResolver(modelResolver); systemContribution.setUnresolved(true); // create an artifact to represent the system defintions and // add it to the contribution List artifacts = systemContribution.getArtifacts(); Artifact artifact = contributionFactory.createArtifact(); artifact.setURI("http://tuscany.apache.org/SystemContribution/Definitions"); artifact.setLocation("Derived"); artifact.setModel(systemDefinitions); artifacts.add(artifact); // don't resolve the system contribution until all the application // level definitions have been added // // // 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 (ExtensionType bindingType : systemDefinitions.getBindingTypes()) { // definitionsResolver.addModel(bindingType); // } // for (ExtensionType 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(Definitions.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 an aggregated SCA definitions model. Must be done before we try and // resolve any contributions or composites as they may depend on the full // definitions.xml picture // get all definitions.xml artifacts from contributions and aggregate // into the system contribution. In turn add a default import into // each contribution so that for unresolved items the resolution // processing will look in the system contribution for (Contribution contribution : workspace.getContributions()) { // aggregate definitions for (Artifact artifact : contribution.getArtifacts()) { Object model = artifact.getModel(); if (model instanceof Definitions) { DefinitionsUtil.aggregate((Definitions)model, systemDefinitions); } } // create a default import and wire it up to the system contribution // model resolver. This is the trick that makes the resolution processing // skip over to the system contribution if resolution is unsuccessful // in the current contribution DefaultImport defaultImport = contributionFactory.createDefaultImport(); defaultImport.setModelResolver(systemContribution.getModelResolver()); contribution.getImports().add(defaultImport); } // now resolve the system contribution and add the contribution // to the workspace contributionProcessor.resolve(systemContribution, workspace.getModelResolver()); workspace.getContributions().add(systemContribution); // TODO - Now we can calculate applicable policy sets for each composite // pre-resolve the contributions contributionsPreresolve( workspace.getContributions(), workspace.getModelResolver() ); // 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()); } } } // Create a top level composite to host our composites // This is temporary to make the activator happy composite = assemblyFactory.createComposite(); composite.setName(new QName(SCA11_TUSCANY_NS, "_tempComposite")); composite.setURI(SCA11_TUSCANY_NS); for (Contribution contribution : workspace.getContributions()) { // find all the (deployable) composites for (Composite deployable: contribution.getDeployables()) { composite.getIncludes().add(deployable); } } // Build the composite and wire the components included in it compositeBuilder.build(composite, systemDefinitions, monitor); analyzeProblems(); // build the endpoint references endpointReferenceBuilder.build(composite, systemDefinitions, monitor); analyzeProblems(); /* composite = configuration.getComposite(); // If a composite was not originally supplied when the Node was created, pick one of the deployable // composites from the supplied contributions. Note: throws an exception if none can be found. if (composite == null) { setDefaultComposite(configuration, workspace); } // Find the composite in the given contributions boolean found = false; if (!useDeploymentComposite) { 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; } // end if } // end for } if (!found) { if (!useDeploymentComposite) { // If the composite was not found, then it must be a separate composite file outside any of the contributions // - a "composite by value" - this requires its URI to be absolute and pointing at the composite file itself. // First read in the composite file to create a composite model object... URI compositeURI = new URI(composite.getURI()); URL compositeURL = compositeURI.toURL(); composite = compositeDocumentProcessor.read(compositeURL, compositeURI, compositeURL); if (composite == null) { throw new IllegalArgumentException("Composite not found: " + compositeURI); } } // Resolve the "composite by value" against the FIRST contribution Contribution contribution = workspace.getContributions().get(0); ModelResolver resolver = contribution.getModelResolver(); compositeProcessor.resolve(composite, resolver); if (composite.isUnresolved()) { throw new IllegalArgumentException("Could not resolve composite: " + composite.getURI() + " in contribution " + contribution.getURI()); } } // end if // Build the composite and wire the components included in it compositeBuilder.build(composite, systemDefinitions, monitor); analyzeProblems(); // build the endpoint references endpointReferenceBuilder.build(composite, systemDefinitions, 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(SCA11_TUSCANY_NS, "_tempComposite")); tempComposite.setURI(SCA11_TUSCANY_NS); // 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); */ } /** * Pre-resolve phase for contributions, to set up handling of imports and exports prior to full resolution * @param contributions - the contributions to preresolve * @param resolver - the ModelResolver to use * @throws ContributionResolveException */ private void contributionsPreresolve( List contributions, ModelResolver resolver ) throws ContributionResolveException { for( Contribution contribution : contributions ) { contributionProcessor.preResolve(contribution, resolver); } // end for } // end method contributionsPreresolve /** * 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()); } } } } /* * Sets a default composite by using any deployable one. */ private void setDefaultComposite(ConfiguredNodeImplementation configuration, Workspace workspace) { // just use the first deployable composite for (Contribution contribution : workspace.getContributions()) { for (Composite c : contribution.getDeployables()) { // Ensure that we pick a composite that has actually been found in its contribution!! if( c.getURI() != null ) { composite = assemblyFactory.createComposite(); composite.setURI(c.getURI()); composite.setUnresolved(true); configuration.setComposite(composite); return; } // end if } // end for } // end for throw new ServiceRuntimeException("No deployable composite found"); } // end method setDefaultComposite public ExtensionPointRegistry getExtensionPoints() { return extensionPoints; } }