From 132aa8a77685ec92bc90c03f987650d275a7b639 Mon Sep 17 00:00:00 2001 From: lresende Date: Mon, 30 Sep 2013 06:59:11 +0000 Subject: 2.0.1 RC1 release tag git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1527464 13f79535-47bb-0310-9956-ffa450edef68 --- .../discovery/impl/LocalDiscoveryService.java | 262 +++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 sca-java-2.x/tags/2.0.1-RC1/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java') diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java b/sca-java-2.x/tags/2.0.1-RC1/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java new file mode 100644 index 0000000000..dc9ae096dd --- /dev/null +++ b/sca-java-2.x/tags/2.0.1-RC1/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java @@ -0,0 +1,262 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.osgi.service.discovery.impl; + +import static org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper.getConfiguration; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_FRAMEWORK_UUID; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_ID; +import static org.osgi.service.remoteserviceadmin.RemoteConstants.ENDPOINT_SERVICE_ID; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; +import java.util.Map.Entry; +import java.util.logging.Level; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.deployment.Deployer; +import org.apache.tuscany.sca.implementation.osgi.SCAConfig; +import org.apache.tuscany.sca.implementation.osgi.ServiceDescription; +import org.apache.tuscany.sca.implementation.osgi.ServiceDescriptions; +import org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicySet; +import org.oasisopen.sca.ServiceRuntimeException; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleEvent; +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.util.tracker.BundleTracker; +import org.osgi.util.tracker.BundleTrackerCustomizer; +import org.osgi.util.tracker.ServiceTracker; + +public class LocalDiscoveryService extends AbstractDiscoveryService implements BundleTrackerCustomizer { + private Deployer deployer; + private BundleTracker bundleTracker; + private Collection extenders = new ArrayList(); + + public LocalDiscoveryService(BundleContext context) { + super(context); + } + + public void start() { + super.start(); + + UtilityExtensionPoint utilities = this.registry.getExtensionPoint(UtilityExtensionPoint.class); + this.deployer = utilities.getUtility(Deployer.class); + bundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STARTING, this); + bundleTracker.open(); + } + + public static ServiceTracker getTracker(BundleContext context) { + Filter filter = null; + try { + filter = + context.createFilter("(& (" + Discovery.SUPPORTED_PROTOCOLS + + "=local) (" + + Constants.OBJECTCLASS + + "=" + + Discovery.class.getName() + + "))"); + } catch (InvalidSyntaxException e) { + throw new IllegalArgumentException(e); + } + return new ServiceTracker(context, filter, null); + } + + private EndpointDescription createEndpointDescription(ServiceDescription sd) { + Map props = new HashMap(sd.getProperties()); + props.put(Constants.OBJECTCLASS, sd.getInterfaces().toArray(new String[sd.getInterfaces().size()])); + if (!props.containsKey(ENDPOINT_SERVICE_ID)) { + props.put(ENDPOINT_SERVICE_ID, Long.valueOf(System.currentTimeMillis())); + } + if (!props.containsKey(ENDPOINT_FRAMEWORK_UUID)) { + props.put(ENDPOINT_FRAMEWORK_UUID, OSGiHelper.getFrameworkUUID(context)); + } + if (!props.containsKey(ENDPOINT_ID)) { + props.put(ENDPOINT_ID, UUID.randomUUID().toString()); + } + + EndpointDescription sed = new EndpointDescription(props); + return sed; + } + + private void removeServicesDeclaredInBundle(Bundle bundle) { + for (Iterator> i = endpointDescriptions.entrySet().iterator(); i.hasNext();) { + Entry entry = i.next(); + if (entry.getValue().equals(bundle)) { + serviceDescriptionRemoved(entry.getKey()); + i.remove(); + } + } + } + + private void serviceDescriptionAdded(EndpointDescription endpointDescription) { + endpointChanged(endpointDescription, ADDED); + } + + private void serviceDescriptionRemoved(EndpointDescription endpointDescription) { + endpointChanged(endpointDescription, REMOVED); + } + + public void stop() { + if (bundleTracker != null) { + bundleTracker.close(); + } + super.stop(); + } + + public Object addingBundle(Bundle bundle, BundleEvent event) { + if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null || bundle.getBundleId() == 0) { + // Ignore fragments + return null; + } + Collection scaConfigs = getConfiguration(bundle, "SCA-Configuration", "OSGI-INF/sca-config/*.xml"); + Collection descriptions = getConfiguration(bundle, "Remote-Service", null); + if (scaConfigs.isEmpty() && descriptions.isEmpty()) { + return null; + } + ExtenderConfiguration extender = new ExtenderConfiguration(); + for (URL url : scaConfigs) { + try { + SCAConfig scaConfig = deployer.loadXMLDocument(url, deployer.createMonitor()); + extender.scaConfigs.add(scaConfig); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + throw new ServiceRuntimeException(e); + } + } + for (URL url : descriptions) { + try { + ServiceDescriptions sds = deployer.loadXMLDocument(url, deployer.createMonitor()); + extender.remoteServiceDescriptions.add(sds); + } catch (Exception e) { + logger.log(Level.SEVERE, e.getMessage(), e); + // throw new ServiceRuntimeException(e); + } + } + + // Add to the extenders before notifying the listeners (the endpoints may references to the config) + ExtenderConfiguration.validate(extenders, extender); + this.extenders.add(extender); + + // Notify + for (ServiceDescriptions sds : extender.getRemoteServiceDescriptions()) { + for (ServiceDescription sd : sds) { + EndpointDescription sed = createEndpointDescription(sd); + endpointDescriptions.put(sed, bundle); + serviceDescriptionAdded(sed); + } + } + + return extender; + } + + public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) { + // STARTING --> ACTIVE + } + + public void removedBundle(Bundle bundle, BundleEvent event, Object object) { + if (object instanceof ExtenderConfiguration) { + extenders.remove((ExtenderConfiguration)object); + removeServicesDeclaredInBundle(bundle); + } + } + + public Collection getConfigurations() { + return extenders; + } + + public static class ExtenderConfiguration { + private Collection scaConfigs = new ArrayList(); + private Collection remoteServiceDescriptions = new ArrayList(); + + public Collection getRemoteServiceDescriptions() { + return remoteServiceDescriptions; + } + + public Collection getSCAConfigs() { + return scaConfigs; + } + + public static void validate(Collection configs, ExtenderConfiguration newConfig) { + Map bindings = new HashMap(); + Map intents = new HashMap(); + Map policySets = new HashMap(); + + for (ExtenderConfiguration config : configs) { + for (SCAConfig c : config.getSCAConfigs()) { + addBindings(bindings, c); + addIntents(intents, c); + addPolicySets(policySets, c); + } + } + for (SCAConfig c : newConfig.getSCAConfigs()) { + addBindings(bindings, c); + addIntents(intents, c); + addPolicySets(policySets, c); + } + } + + private static void addIntents(Map intents, SCAConfig c) { + for (Intent i: c.getIntents()) { + if (intents.put(i.getName(), i) != null) { + throw new ServiceRuntimeException("Duplicate intent: " + i.getName()); + } + } + } + + private static void addPolicySets(Map policySets, SCAConfig c) { + for (PolicySet ps: c.getPolicySets()) { + if (policySets.put(ps.getName(), ps) != null) { + throw new ServiceRuntimeException("Duplicate policySet: " + ps.getName()); + } + } + } + + private static void addBindings(Map bindings, SCAConfig c) { + for (Binding b : c.getBindings()) { + QName name = new QName(c.getTargetNamespace(), b.getName()); + if (bindings.put(name, b) != null) { + throw new ServiceRuntimeException("Duplicate binding: " + name); + } + } + } + + } + + @Override + protected Dictionary getProperties() { + Dictionary props = super.getProperties(); + props.put(SUPPORTED_PROTOCOLS, new String[] {"local"}); + return props; + } + +} -- cgit v1.2.3