blob: 63af213fbb7363a5ddbfa144760c144e869e4144 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tuscany.sca.domain.manager.impl;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.compositeAlternateLink;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.compositeKey;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.compositeQName;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.compositeSourceLink;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.compositeTitle;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.contributionURI;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.lastModified;
import static org.apache.tuscany.sca.domain.manager.impl.DomainManagerUtil.locationURL;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.Component;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.Composite;
import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor;
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.ModelResolverExtensionPoint;
import org.apache.tuscany.sca.contribution.service.ContributionReadException;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.data.collection.Entry;
import org.apache.tuscany.sca.data.collection.Item;
import org.apache.tuscany.sca.data.collection.ItemCollection;
import org.apache.tuscany.sca.data.collection.LocalItemCollection;
import org.apache.tuscany.sca.data.collection.NotFoundException;
import org.apache.tuscany.sca.domain.manager.impl.DeployableCompositeCollectionImpl.Cache.ContributionCache;
import org.apache.tuscany.sca.implementation.node.NodeImplementation;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.MonitorFactory;
import org.apache.tuscany.sca.workspace.builder.ContributionDependencyBuilder;
import org.apache.tuscany.sca.workspace.builder.impl.ContributionDependencyBuilderImpl;
import org.apache.tuscany.sca.workspace.processor.impl.ContributionContentProcessor;
import org.osoa.sca.annotations.Init;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;
import org.osoa.sca.annotations.Service;
/**
* Implementation of a deployable composite collection service.
*
* @version $Rev$ $Date$
*/
@Scope("COMPOSITE")
@Service(interfaces = { ItemCollection.class, LocalItemCollection.class, ContributionsReader.class })
public class DeployableCompositeCollectionImpl implements ItemCollection,
LocalItemCollection, ContributionsReader {
private static final Logger logger = Logger
.getLogger(DeployableCompositeCollectionImpl.class.getName());
@Reference
public LocalItemCollection contributionCollection;
@Reference
public DomainManagerConfiguration domainManagerConfiguration;
private ModelFactoryExtensionPoint modelFactories;
private ModelResolverExtensionPoint modelResolvers;
private URLArtifactProcessor<Contribution> contributionProcessor;
private XMLOutputFactory outputFactory;
private ContributionDependencyBuilder contributionDependencyBuilder;
private Monitor monitor;
/**
* Cache contribution models.
*/
static class Cache {
static class ContributionCache {
private Contribution contribution;
private long contributionLastModified;
}
private Map<URL, ContributionCache> contributions = new HashMap<URL, ContributionCache>();
}
private Cache cache = new Cache();
/**
* Initialize the component.
*/
@Init
public void initialize() throws ParserConfigurationException {
ExtensionPointRegistry extensionPoints = domainManagerConfiguration
.getExtensionPoints();
// Create a monitor
UtilityExtensionPoint utilities = extensionPoints
.getExtensionPoint(UtilityExtensionPoint.class);
MonitorFactory monitorFactory = utilities
.getUtility(MonitorFactory.class);
monitor = monitorFactory.createMonitor();
// Get model factories
modelFactories = extensionPoints
.getExtensionPoint(ModelFactoryExtensionPoint.class);
XMLInputFactory inputFactory = modelFactories
.getFactory(XMLInputFactory.class);
outputFactory = modelFactories.getFactory(XMLOutputFactory.class);
outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES,
true);
// Get and initialize artifact processors
StAXArtifactProcessorExtensionPoint staxProcessors = extensionPoints
.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
StAXArtifactProcessor<Object> staxProcessor = new ExtensibleStAXArtifactProcessor(
staxProcessors, inputFactory, outputFactory, monitor);
URLArtifactProcessorExtensionPoint urlProcessors = extensionPoints
.getExtensionPoint(URLArtifactProcessorExtensionPoint.class);
URLArtifactProcessor<Object> urlProcessor = new ExtensibleURLArtifactProcessor(
urlProcessors, monitor);
// Create contribution processor
modelResolvers = extensionPoints
.getExtensionPoint(ModelResolverExtensionPoint.class);
contributionProcessor = new ContributionContentProcessor(
extensionPoints, monitor);
// Create contribution and composite builders
contributionDependencyBuilder = new ContributionDependencyBuilderImpl(
monitor);
}
public Entry<String, Item>[] getAll() {
logger.fine("getAll");
// Return all the deployable composites in the contributions
List<Entry<String, Item>> entries = new ArrayList<Entry<String, Item>>();
// Get the list of contributions in the workspace
Entry<String, Item>[] contributionEntries = contributionCollection
.getAll();
// Read contribution metadata
for (Entry<String, Item> contributionEntry : contributionEntries) {
Item contributionItem = contributionEntry.getData();
Contribution contribution;
try {
contribution = contribution(contributionEntry.getKey(),
contributionItem.getAlternate());
} catch (ContributionReadException e) {
continue;
}
// Create entries for the deployable composites
for (Composite deployable : contribution.getDeployables()) {
entries.add(entry(contribution, deployable));
}
}
return entries.toArray(new Entry[entries.size()]);
}
public Contribution[] readContributions() {
// Get the list of contributions in the workspace
Entry<String, Item>[] contributionEntries = contributionCollection
.getAll();
LinkedList<Contribution> contributions = new LinkedList<Contribution>();
// Read contribution metadata
for (Entry<String, Item> contributionEntry : contributionEntries) {
Item contributionItem = contributionEntry.getData();
Contribution contribution;
try {
contribution = contribution(contributionEntry.getKey(),
contributionItem.getAlternate());
} catch (ContributionReadException e) {
continue;
}
LinkedList<Composite> resolvedComposites = new LinkedList<Composite>();
for (Composite composite : contribution.getDeployables()) {
// find the deployable composite
composite = contribution.getModelResolver().resolveModel(
Composite.class, composite);
resolvedComposites.add(composite);
}
contribution.getDeployables().clear();
contribution.getDeployables().addAll(resolvedComposites);
contributions.add(contribution);
}
return contributions.toArray(new Contribution[0]);
}
public Item get(String key) throws NotFoundException {
logger.fine("get " + key);
// Get the specified contribution info
String contributionURI = contributionURI(key);
Item contributionItem = contributionCollection.get(contributionURI);
// Read the contribution
Contribution contribution;
try {
contribution = contribution(contributionURI, contributionItem
.getAlternate());
} catch (ContributionReadException e) {
throw new NotFoundException(key);
}
// Find the specified deployable composite
QName qname = compositeQName(key);
for (Composite deployable : contribution.getDeployables()) {
if (qname.equals(deployable.getName())) {
// find the deployable composite
deployable = contribution.getModelResolver().resolveModel(
Composite.class, deployable);
if (deployable.isUnresolved()) {
throw new NotFoundException(key);
}
// Return an item describing the deployable composite
return item(contribution, deployable);
}
}
throw new NotFoundException(key);
}
public String post(String key, Item item) {
throw new UnsupportedOperationException();
}
public void put(String key, Item item) throws NotFoundException {
throw new UnsupportedOperationException();
}
public void delete(String key) throws NotFoundException {
throw new UnsupportedOperationException();
}
public Entry<String, Item>[] query(String queryString) {
logger.fine("query " + queryString);
if (queryString.startsWith("contribution=")) {
// Return all the deployable composites in the specified
// contribution
List<Entry<String, Item>> entries = new ArrayList<Entry<String, Item>>();
// Get the specified contribution info
String contributionURI = queryString.substring(queryString
.indexOf('=') + 1);
Item contributionItem;
try {
contributionItem = contributionCollection.get(contributionURI);
} catch (NotFoundException e) {
return entries.toArray(new Entry[entries.size()]);
}
// Read the contribution
Contribution contribution;
try {
contribution = contribution(contributionURI, contributionItem
.getAlternate());
} catch (ContributionReadException e) {
return entries.toArray(new Entry[entries.size()]);
}
// Create entries for the deployable composites
for (Composite deployable : contribution.getDeployables()) {
entries.add(entry(contribution, deployable));
}
return entries.toArray(new Entry[entries.size()]);
} else {
throw new UnsupportedOperationException();
}
}
/**
* Returns the contribution with the given URI.
*
* @param contributionURI
* @param contributionLocation
* @return
* @throws NotFoundException
*/
private Contribution contribution(String contributionURI,
String contributionLocation) throws ContributionReadException {
try {
URI uri = URI.create(contributionURI);
URL location = locationURL(contributionLocation);
// Get contribution from cache
ContributionCache contributionCache = cache.contributions
.get(location);
long lastModified = lastModified(location);
if (contributionCache != null) {
if (contributionCache.contributionLastModified == lastModified) {
return contributionCache.contribution;
}
// Reset contribution cache
cache.contributions.remove(location);
}
Contribution contribution = (Contribution) contributionProcessor
.read(null, uri, location);
// TODO - analyse dependencies here?
// contributionProcessor.resolve(contribution, new
// DefaultModelResolver());
// Cache contribution
contributionCache = new ContributionCache();
contributionCache.contribution = contribution;
contributionCache.contributionLastModified = lastModified;
cache.contributions.put(location, contributionCache);
return contribution;
} catch (ContributionReadException e) {
throw e;
} catch (MalformedURLException e) {
throw new ContributionReadException(e);
// } catch (ContributionResolveException e) {
// throw new ContributionReadException(e);
} catch (Throwable e) {
throw new ContributionReadException(e);
}
}
/**
* Returns the entry contents describing a composite.
*
* @param composite
* @return
*/
private static String content(Composite composite) {
StringBuffer sb = new StringBuffer();
List<Component> components = composite.getComponents();
for (int i = 0, n = components.size(); i < n; i++) {
Component component = components.get(i);
if (component.getImplementation() instanceof NodeImplementation) {
List<ComponentService> services = component.getServices();
if (!services.isEmpty()) {
List<Binding> bindings = services.get(0).getBindings();
if (!bindings.isEmpty()) {
// List node URIs
sb.append("Node URI: <span id=\"nodeURI\">");
sb.append(component.getServices().get(0).getBindings()
.get(0).getURI());
break;
}
}
} else {
// List component names
if (sb.length() == 0) {
sb.append("Components: <span id=\"components\">");
} else {
sb.append(" ");
}
sb.append(component.getName());
}
}
if (sb.length() != 0) {
sb.append("</span>");
}
return sb.toString();
}
/**
* Returns the link to the resource related to a composite.
*
* @param composite
* @return
*/
private static String relatedLink(Composite composite) {
for (Component component : composite.getComponents()) {
if (component.getImplementation() instanceof NodeImplementation) {
NodeImplementation nodeImplementation = (NodeImplementation) component
.getImplementation();
Composite deployable = nodeImplementation.getComposite();
String contributionURI = deployable.getURI();
QName qname = deployable.getName();
String key = compositeKey(contributionURI, qname);
return "/composite-source/" + key;
}
}
return null;
}
/**
* Returns an entry describing the given deployable.
*
* @param contribution
* @param deployable
* @return
*/
private static Entry<String, Item> entry(Contribution contribution,
Composite deployable) {
Entry<String, Item> entry = new Entry<String, Item>();
entry.setKey(DomainManagerUtil.compositeKey(contribution.getURI(),
deployable.getName()));
entry.setData(item(contribution, deployable));
return entry;
}
/**
* Returns an item describing the given deployable.
*
* @param contribution
* @param deployable
* @return
*/
private static Item item(Contribution contribution, Composite deployable) {
String contributionURI = contribution.getURI();
String contributionLocation = contribution.getLocation();
QName qname = deployable.getName();
String deployableURI = deployable.getURI();
Item item = new Item();
item.setTitle(compositeTitle(contributionURI, qname));
item.setContents(content(deployable));
item.setLink(compositeSourceLink(contributionURI, qname));
item.setAlternate(compositeAlternateLink(contributionLocation,
deployableURI));
item.setRelated(relatedLink(deployable));
return item;
}
}