http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java new file mode 100644 index 0000000..60da887 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminCore.java @@ -0,0 +1,590 @@ +/** + * 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.aries.rsa.core; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.aries.rsa.spi.DistributionProvider; +import org.apache.aries.rsa.spi.Endpoint; +import org.apache.aries.rsa.util.EndpointHelper; +import org.apache.aries.rsa.util.StringPlus; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceEvent; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; +import org.osgi.service.remoteserviceadmin.ExportRegistration; +import org.osgi.service.remoteserviceadmin.ImportReference; +import org.osgi.service.remoteserviceadmin.ImportRegistration; +import org.osgi.service.remoteserviceadmin.RemoteConstants; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RemoteServiceAdminCore implements RemoteServiceAdmin { + + private static final Logger LOG = LoggerFactory.getLogger(RemoteServiceAdminCore.class); + + private final Map<Map<String, Object>, Collection<ExportRegistration>> exportedServices + = new LinkedHashMap<Map<String, Object>, Collection<ExportRegistration>>(); + private final Map<EndpointDescription, Collection<ImportRegistrationImpl>> importedServices + = new LinkedHashMap<EndpointDescription, Collection<ImportRegistrationImpl>>(); + + // Is stored in exportedServices while the export is in progress as a marker + private final List<ExportRegistration> exportInProgress = Collections.emptyList(); + + private final BundleContext bctx; + private final EventProducer eventProducer; + private final ServiceListener exportedServiceListener; + private DistributionProvider provider; + private BundleContext apictx; + + public RemoteServiceAdminCore(BundleContext context, BundleContext apiContext, DistributionProvider provider) { + this.bctx = context; + this.apictx = apiContext; + this.eventProducer = new EventProducer(bctx); + this.provider = provider; + // listen for exported services being unregistered so we can close the export + this.exportedServiceListener = new ServiceListener() { + public void serviceChanged(ServiceEvent event) { + if (event.getType() == ServiceEvent.UNREGISTERING) { + removeServiceExports(event.getServiceReference()); + } + } + }; + try { + String filter = "(" + RemoteConstants.SERVICE_EXPORTED_INTERFACES + "=*)"; + context.addServiceListener(exportedServiceListener, filter); + } catch (InvalidSyntaxException ise) { + throw new RuntimeException(ise); // can never happen + } + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public List<ExportRegistration> exportService(ServiceReference serviceReference, Map additionalProperties) + throws IllegalArgumentException, UnsupportedOperationException { + Map<String, Object> serviceProperties = getProperties(serviceReference); + if (additionalProperties != null) { + overlayProperties(serviceProperties, additionalProperties); + } + Map<String, Object> key = makeKey(serviceProperties); + + List<String> interfaceNames = getInterfaceNames(serviceProperties); + + if (isImportedService(serviceReference)) { + return Collections.emptyList(); + } + + List<ExportRegistration> exportRegs = getExistingAndLock(key, interfaceNames); + if (exportRegs != null) { + return exportRegs; + } + + try { + ExportRegistration exportReg = exportService(interfaceNames, serviceReference, serviceProperties); + exportRegs = new ArrayList<>(); + exportRegs.add(exportReg); + store(key, exportRegs); + return exportRegs; + } finally { + unlock(key); + } + } + + private void store(Map<String, Object> key, List<ExportRegistration> exportRegs) { + if (!exportRegs.isEmpty()) { + // enlist initial export registrations in global list of exportRegistrations + synchronized (exportedServices) { + exportedServices.put(key, new ArrayList<ExportRegistration>(exportRegs)); + } + eventProducer.publishNotification(exportRegs); + } + } + + private void unlock(Map<String, Object> key) { + synchronized (exportedServices) { + if (exportedServices.get(key) == exportInProgress) { + exportedServices.remove(key); + } + exportedServices.notifyAll(); // in any case, always notify waiting threads + } + } + + private List<ExportRegistration> getExistingAndLock(Map<String, Object> key, List<String> interfaces) { + synchronized (exportedServices) { + // check if it is already exported... + Collection<ExportRegistration> existingRegs = exportedServices.get(key); + + // if the export is already in progress, wait for it to be complete + while (existingRegs == exportInProgress) { + try { + exportedServices.wait(); + existingRegs = exportedServices.get(key); + } catch (InterruptedException ie) { + LOG.debug("interrupted while waiting for export in progress"); + return Collections.emptyList(); + } + } + + // if the export is complete, return a copy of existing export + if (existingRegs != null) { + LOG.debug("already exported this service. Returning existing exportRegs {} ", interfaces); + return copyExportRegistration(existingRegs); + } + + // mark export as being in progress + exportedServices.put(key, exportInProgress); + } + return null; + } + + private ExportRegistration exportService(List<String> interfaceNames, + ServiceReference<?> serviceReference, Map<String, Object> serviceProperties) { + LOG.info("interfaces selected for export: " + interfaceNames); + try { + Class<?>[] interfaces = getInterfaces(interfaceNames, serviceReference.getBundle()); + Map<String, Object> eprops = createEndpointProps(serviceProperties, interfaces); + BundleContext serviceContext = serviceReference.getBundle().getBundleContext(); + + // TODO unget service when export is destroyed + Object serviceO = serviceContext.getService(serviceReference); + Endpoint endpoint = provider.exportService(serviceO, serviceContext, eprops, interfaces); + return new ExportRegistrationImpl(serviceReference, endpoint, this); + } catch (Exception e) { + return new ExportRegistrationImpl(this, e); + } + } + + private Class<?>[] getInterfaces(List<String> interfaceNames, + Bundle serviceBundle) throws ClassNotFoundException { + List<Class<?>> interfaces = new ArrayList<>(); + for (String interfaceName : interfaceNames) { + interfaces.add(serviceBundle.loadClass(interfaceName)); + } + return interfaces.toArray(new Class[]{}); + } + + /** + * Determines which interfaces should be exported. + * + * @param serviceProperties the exported service properties + * @return the interfaces to be exported + * @throws IllegalArgumentException if the service parameters are invalid + * @see RemoteServiceAdmin#exportService + * @see org.osgi.framework.Constants#OBJECTCLASS + * @see RemoteConstants#SERVICE_EXPORTED_INTERFACES + */ + private List<String> getInterfaceNames(Map<String, Object> serviceProperties) { + List<String> providedInterfaces = StringPlus.normalize(serviceProperties.get(org.osgi.framework.Constants.OBJECTCLASS)); + if (providedInterfaces == null || providedInterfaces.isEmpty()) { + throw new IllegalArgumentException("service is missing the objectClass property"); + } + + List<String> exportedInterfaces + = StringPlus.normalize(serviceProperties.get(RemoteConstants.SERVICE_EXPORTED_INTERFACES)); + if (exportedInterfaces == null || exportedInterfaces.isEmpty()) { + throw new IllegalArgumentException("service is missing the service.exported.interfaces property"); + } + + List<String> interfaces = new ArrayList<String>(1); + if (exportedInterfaces.size() == 1 && "*".equals(exportedInterfaces.get(0))) { + // FIXME: according to the spec, this should only return the interfaces, and not + // non-interface classes (which are valid OBJECTCLASS values, even if discouraged) + interfaces.addAll(providedInterfaces); + } else { + List<String> providedList = providedInterfaces; + List<String> allowedList = exportedInterfaces; + if (!providedList.containsAll(allowedList)) { + throw new IllegalArgumentException(String.format( + "exported interfaces %s must be a subset of the service's registered types %s", + allowedList, providedList)); + } + + interfaces.addAll(exportedInterfaces); + } + return interfaces; + } + + /** + * Converts the given properties map into one that can be used as a map key itself. + * For example, if a value is an array, it is converted into a list so that the + * equals method will compare it properly. + * + * @param properties a properties map + * @return a map that represents the given map, but can be safely used as a map key itself + */ + private Map<String, Object> makeKey(Map<String, Object> properties) { + // FIXME: we should also make logically equal values actually compare as equal + // (e.g. String+ values should be normalized) + Map<String, Object> converted = new HashMap<String, Object>(properties.size()); + for (Map.Entry<String, Object> entry : properties.entrySet()) { + Object val = entry.getValue(); + // convert arrays into lists so that they can be compared via equals() + if (val instanceof Object[]) { + val = Arrays.asList((Object[])val); + } + converted.put(entry.getKey(), val); + } + return converted; + } + + private List<ExportRegistration> copyExportRegistration(Collection<ExportRegistration> regs) { + Set<EndpointDescription> copiedEndpoints = new HashSet<EndpointDescription>(); + + // create a new list with copies of the exportRegistrations + List<ExportRegistration> copy = new ArrayList<ExportRegistration>(regs.size()); + for (ExportRegistration exportRegistration : regs) { + if (exportRegistration instanceof ExportRegistrationImpl) { + ExportRegistrationImpl exportRegistrationImpl = (ExportRegistrationImpl) exportRegistration; + EndpointDescription epd = exportRegistration.getExportReference().getExportedEndpoint(); + // create one copy for each distinct endpoint description + if (!copiedEndpoints.contains(epd)) { + copiedEndpoints.add(epd); + copy.add(new ExportRegistrationImpl(exportRegistrationImpl)); + } + } + } + + regs.addAll(copy); + + eventProducer.publishNotification(copy); + return copy; + } + + private boolean isImportedService(ServiceReference<?> sref) { + return sref.getProperty(RemoteConstants.SERVICE_IMPORTED) != null; + } + + @Override + public Collection<ExportReference> getExportedServices() { + synchronized (exportedServices) { + List<ExportReference> ers = new ArrayList<ExportReference>(); + for (Collection<ExportRegistration> exportRegistrations : exportedServices.values()) { + for (ExportRegistration er : exportRegistrations) { + ers.add(new ExportReferenceImpl(er.getExportReference())); + } + } + return Collections.unmodifiableCollection(ers); + } + } + + @Override + public Collection<ImportReference> getImportedEndpoints() { + synchronized (importedServices) { + List<ImportReference> irs = new ArrayList<ImportReference>(); + for (Collection<ImportRegistrationImpl> irl : importedServices.values()) { + for (ImportRegistrationImpl impl : irl) { + irs.add(impl.getImportReference()); + } + } + return Collections.unmodifiableCollection(irs); + } + } + + /** + * Importing form here... + */ + @Override + public ImportRegistration importService(EndpointDescription endpoint) { + LOG.debug("importService() Endpoint: {}", endpoint.getProperties()); + + synchronized (importedServices) { + Collection<ImportRegistrationImpl> imRegs = importedServices.get(endpoint); + if (imRegs != null && !imRegs.isEmpty()) { + LOG.debug("creating copy of existing import registrations"); + ImportRegistrationImpl irParent = imRegs.iterator().next(); + ImportRegistrationImpl ir = new ImportRegistrationImpl(irParent); + imRegs.add(ir); + eventProducer.publishNotification(ir); + return ir; + } + + if (determineConfigTypesForImport(endpoint).size() == 0) { + LOG.info("No matching handler can be found for remote endpoint {}.", endpoint.getId()); + return null; + } + + // TODO: somehow select the interfaces that should be imported ---> job of the TopologyManager? + List<String> matchingInterfaces = endpoint.getInterfaces(); + + if (matchingInterfaces.size() == 0) { + LOG.info("No matching interfaces found for remote endpoint {}.", endpoint.getId()); + return null; + } + + LOG.info("Importing service {} with interfaces {} using handler {}.", + endpoint.getId(), endpoint.getInterfaces(), provider.getClass()); + + ImportRegistrationImpl imReg = exposeServiceFactory(matchingInterfaces.get(0), endpoint, provider); + if (imRegs == null) { + imRegs = new ArrayList<ImportRegistrationImpl>(); + importedServices.put(endpoint, imRegs); + } + imRegs.add(imReg); + eventProducer.publishNotification(imReg); + return imReg; + } + } + + private List<String> determineConfigTypesForImport(EndpointDescription endpoint) { + List<String> remoteConfigurationTypes = endpoint.getConfigurationTypes(); + + List<String> usableConfigurationTypes = new ArrayList<String>(); + for (String ct : provider.getSupportedTypes()) { + if (remoteConfigurationTypes.contains(ct)) { + usableConfigurationTypes.add(ct); + } + } + + if (usableConfigurationTypes.size() == 0) { + LOG.info("Ignoring endpoint {} as it has no compatible configuration types: {}.", + endpoint.getId(), remoteConfigurationTypes); + } + return usableConfigurationTypes; + } + + protected ImportRegistrationImpl exposeServiceFactory(String interfaceName, + EndpointDescription epd, + DistributionProvider handler) { + ImportRegistrationImpl imReg = new ImportRegistrationImpl(epd, this); + try { + EndpointDescription endpoint = imReg.getImportedEndpointDescription(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(endpoint.getProperties()); + serviceProps.put(RemoteConstants.SERVICE_IMPORTED, true); + serviceProps.remove(RemoteConstants.SERVICE_EXPORTED_INTERFACES); + + ClientServiceFactory csf = new ClientServiceFactory(endpoint, handler, imReg); + imReg.setClientServiceFactory(csf); + + /** + * Export the factory using the api context as it has very few imports. + * If the bundle publishing the factory does not import the service interface + * package then the factory is visible for all consumers which we want. + */ + ServiceRegistration<?> csfReg = apictx.registerService(interfaceName, csf, serviceProps); + imReg.setImportedServiceRegistration(csfReg); + } catch (Exception ex) { + // Only logging at debug level as this might be written to the log at the TopologyManager + LOG.debug("Can not proxy service with interface " + interfaceName + ": " + ex.getMessage(), ex); + imReg.setException(ex); + } + return imReg; + } + + /** + * Removes and closes all exports for the given service. + * This is called when the service is unregistered. + * + * @param sref the service whose exports should be removed and closed + */ + protected void removeServiceExports(ServiceReference<?> sref) { + List<ExportRegistration> regs = new ArrayList<ExportRegistration>(1); + synchronized (exportedServices) { + for (Iterator<Collection<ExportRegistration>> it = exportedServices.values().iterator(); it.hasNext();) { + Collection<ExportRegistration> value = it.next(); + for (Iterator<ExportRegistration> it2 = value.iterator(); it2.hasNext();) { + ExportRegistration er = it2.next(); + if (er.getExportReference().getExportedService().equals(sref)) { + regs.add(er); + } + } + } + // do this outside of iteration to avoid concurrent modification + for (ExportRegistration er : regs) { + LOG.debug("closing export for service {}", sref); + er.close(); + } + } + + } + + /** + * Removes the provided Export Registration from the internal management structures. + * This is called from the ExportRegistration itself when it is closed (so should + * not attempt to close it again here). + * + * @param eri the export registration to remove + */ + protected void removeExportRegistration(ExportRegistrationImpl eri) { + synchronized (exportedServices) { + for (Iterator<Collection<ExportRegistration>> it = exportedServices.values().iterator(); it.hasNext();) { + Collection<ExportRegistration> value = it.next(); + for (Iterator<ExportRegistration> it2 = value.iterator(); it2.hasNext();) { + ExportRegistration er = it2.next(); + if (er.equals(eri)) { + eventProducer.notifyRemoval(eri); + it2.remove(); + if (value.isEmpty()) { + it.remove(); + } + return; + } + } + } + } + } + + // remove all export registrations associated with the given bundle + protected void removeExportRegistrations(Bundle exportingBundle) { + List<ExportRegistration> bundleExports = getExportsForBundle(exportingBundle); + for (ExportRegistration export : bundleExports) { + export.close(); + } + } + + // remove all import registrations + protected void removeImportRegistrations() { + Collection<ImportRegistrationImpl> copy = new ArrayList<ImportRegistrationImpl>(); + synchronized (importedServices) { + for (Collection<ImportRegistrationImpl> irs : importedServices.values()) { + copy.addAll(irs); + } + } + for (ImportRegistrationImpl ir : copy) { + removeImportRegistration(ir); + } + } + + private List<ExportRegistration> getExportsForBundle(Bundle exportingBundle) { + synchronized (exportedServices) { + List<ExportRegistration> bundleRegs = new ArrayList<ExportRegistration>(); + for (Collection<ExportRegistration> regs : exportedServices.values()) { + if (!regs.isEmpty()) { + ExportRegistration exportRegistration = regs.iterator().next(); + if (exportRegistration.getException() == null) { + Bundle regBundle = exportRegistration.getExportReference().getExportedService().getBundle(); + if (exportingBundle.equals(regBundle)) { + bundleRegs.addAll(regs); + } + } + } + } + return bundleRegs; + } + } + + protected void removeImportRegistration(ImportRegistrationImpl iri) { + synchronized (importedServices) { + LOG.debug("Removing importRegistration {}", iri); + + Collection<ImportRegistrationImpl> imRegs = importedServices.get(iri.getImportedEndpointAlways()); + if (imRegs != null && imRegs.contains(iri)) { + imRegs.remove(iri); + eventProducer.notifyRemoval(iri); + } + if (imRegs == null || imRegs.isEmpty()) { + importedServices.remove(iri.getImportedEndpointAlways()); + } + } + } + + public void close() { + removeImportRegistrations(); + bctx.removeServiceListener(exportedServiceListener); + } + + static void overlayProperties(Map<String, Object> serviceProperties, + Map<String, Object> additionalProperties) { + Map<String, String> keysLowerCase = new HashMap<String, String>(); + for (String key : serviceProperties.keySet()) { + keysLowerCase.put(key.toLowerCase(), key); + } + + for (Map.Entry<String, Object> e : additionalProperties.entrySet()) { + String key = e.getKey(); + String lowerKey = key.toLowerCase(); + if (org.osgi.framework.Constants.SERVICE_ID.toLowerCase().equals(lowerKey) + || org.osgi.framework.Constants.OBJECTCLASS.toLowerCase().equals(lowerKey)) { + // objectClass and service.id must not be overwritten + LOG.info("exportService called with additional properties map that contained illegal key: " + + key + ", the key is ignored"); + } else { + String origKey = keysLowerCase.get(lowerKey); + if (origKey != null) { + LOG.debug("Overwriting property [{}] with value [{}]", origKey, e.getValue()); + } else { + origKey = key; + keysLowerCase.put(lowerKey, origKey); + } + serviceProperties.put(origKey, e.getValue()); + } + } + } + + /** + * Returns a service's properties as a map. + * + * @param serviceReference a service reference + * @return the service's properties as a map + */ + private Map<String, Object> getProperties(ServiceReference<?> serviceReference) { + String[] keys = serviceReference.getPropertyKeys(); + Map<String, Object> props = new HashMap<String, Object>(keys.length); + for (String key : keys) { + Object val = serviceReference.getProperty(key); + props.put(key, val); + } + return props; + } + + protected Map<String, Object> createEndpointProps(Map<String, Object> effectiveProps, + Class<?>[] ifaces) { + Map<String, Object> props = new HashMap<String, Object>(); + copyEndpointProperties(effectiveProps, props); + props.remove(org.osgi.framework.Constants.SERVICE_ID); + EndpointHelper.addObjectClass(props, ifaces); + props.put(RemoteConstants.ENDPOINT_SERVICE_ID, effectiveProps.get(org.osgi.framework.Constants.SERVICE_ID)); + String frameworkUUID = bctx.getProperty(org.osgi.framework.Constants.FRAMEWORK_UUID); + props.put(RemoteConstants.ENDPOINT_FRAMEWORK_UUID, frameworkUUID); + for (Class<?> iface : ifaces) { + String pkg = iface.getPackage().getName(); + props.put(RemoteConstants.ENDPOINT_PACKAGE_VERSION_ + pkg, PackageUtil.getVersion(iface, bctx)); + } + return props; + } + + + + private void copyEndpointProperties(Map<String, Object> sd, Map<String, Object> endpointProps) { + Set<Map.Entry<String, Object>> keys = sd.entrySet(); + for (Map.Entry<String, Object> entry : keys) { + String skey = entry.getKey(); + if (!skey.startsWith(".")) { + endpointProps.put(skey, entry.getValue()); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminInstance.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminInstance.java b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminInstance.java new file mode 100644 index 0000000..1b1c8da --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceAdminInstance.java @@ -0,0 +1,99 @@ +/** + * 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.aries.rsa.core; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.EndpointPermission; +import org.osgi.service.remoteserviceadmin.ExportReference; +import org.osgi.service.remoteserviceadmin.ExportRegistration; +import org.osgi.service.remoteserviceadmin.ImportReference; +import org.osgi.service.remoteserviceadmin.ImportRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; + +public class RemoteServiceAdminInstance implements RemoteServiceAdmin { + + private final BundleContext bctx; + private final RemoteServiceAdminCore rsaCore; + + private boolean closed; + + public RemoteServiceAdminInstance(BundleContext bc, RemoteServiceAdminCore core) { + bctx = bc; + rsaCore = core; + } + + @Override + @SuppressWarnings("rawtypes") + public List<ExportRegistration> exportService(final ServiceReference ref, final Map properties) { + checkPermission(new EndpointPermission("*", EndpointPermission.EXPORT)); + return AccessController.doPrivileged(new PrivilegedAction<List<ExportRegistration>>() { + public List<ExportRegistration> run() { + return closed ? Collections.<ExportRegistration>emptyList() : rsaCore.exportService(ref, properties); + } + }); + } + + @Override + public Collection<ExportReference> getExportedServices() { + checkPermission(new EndpointPermission("*", EndpointPermission.READ)); + return closed ? null : rsaCore.getExportedServices(); + } + + @Override + public Collection<ImportReference> getImportedEndpoints() { + checkPermission(new EndpointPermission("*", EndpointPermission.READ)); + return closed ? null : rsaCore.getImportedEndpoints(); + } + + @Override + public ImportRegistration importService(final EndpointDescription endpoint) { + String frameworkUUID = bctx.getProperty(Constants.FRAMEWORK_UUID); + checkPermission(new EndpointPermission(endpoint, frameworkUUID, EndpointPermission.IMPORT)); + return AccessController.doPrivileged(new PrivilegedAction<ImportRegistration>() { + public ImportRegistration run() { + return closed ? null : rsaCore.importService(endpoint); + } + }); + } + + public void close(boolean closeAll) { + closed = true; + rsaCore.removeExportRegistrations(bctx.getBundle()); + if (closeAll) { + rsaCore.close(); + } + } + + private void checkPermission(EndpointPermission permission) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(permission); + } + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceadminFactory.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceadminFactory.java b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceadminFactory.java new file mode 100644 index 0000000..51abb65 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/RemoteServiceadminFactory.java @@ -0,0 +1,51 @@ +/** + * 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.aries.rsa.core; + +import org.osgi.framework.Bundle; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RemoteServiceadminFactory implements ServiceFactory<RemoteServiceAdmin> { + + private static final Logger LOG = LoggerFactory.getLogger(RemoteServiceadminFactory.class); + + private final RemoteServiceAdminCore rsaCore; + private int instances; + + public RemoteServiceadminFactory(RemoteServiceAdminCore rsaCore) { + this.rsaCore = rsaCore; + } + + public synchronized RemoteServiceAdmin getService(Bundle b, ServiceRegistration<RemoteServiceAdmin> sreg) { + LOG.debug("new RemoteServiceAdmin ServiceInstance created for Bundle {}", b.getSymbolicName()); + instances++; + return new RemoteServiceAdminInstance(b.getBundleContext(), rsaCore); + } + + public synchronized void ungetService(Bundle b, ServiceRegistration<RemoteServiceAdmin> sreg, + RemoteServiceAdmin serviceObject) { + LOG.debug("RemoteServiceAdmin ServiceInstance removed for Bundle {}", b.getSymbolicName()); + instances--; + ((RemoteServiceAdminInstance)serviceObject).close(instances == 0); + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/Activator.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/Activator.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/Activator.java deleted file mode 100644 index 4c4d7ad..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/Activator.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class Activator implements BundleActivator { - - private DistributionProviderTracker tracker; - - public void start(BundleContext bundlecontext) throws Exception { - tracker = new DistributionProviderTracker(bundlecontext); - tracker.open(); - } - - public void stop(BundleContext context) throws Exception { - tracker.close(); - } - -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ClientServiceFactory.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ClientServiceFactory.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ClientServiceFactory.java deleted file mode 100644 index 7c292db..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ClientServiceFactory.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.cxf.dosgi.dsw.api.DistributionProvider; -import org.apache.cxf.dosgi.dsw.api.IntentUnsatisfiedException; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceFactory; -import org.osgi.framework.ServiceRegistration; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.service.remoteserviceadmin.EndpointDescription; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings("rawtypes") -public class ClientServiceFactory implements ServiceFactory { - - private static final Logger LOG = LoggerFactory.getLogger(ClientServiceFactory.class); - - private EndpointDescription endpoint; - private DistributionProvider handler; - private ImportRegistrationImpl importRegistration; - - private boolean closeable; - private int serviceCounter; - - public ClientServiceFactory(EndpointDescription endpoint, - DistributionProvider handler, ImportRegistrationImpl ir) { - this.endpoint = endpoint; - this.handler = handler; - this.importRegistration = ir; - } - - public Object getService(final Bundle requestingBundle, final ServiceRegistration sreg) { - List<String> interfaceNames = endpoint.getInterfaces(); - final BundleContext consumerContext = requestingBundle.getBundleContext(); - final ClassLoader consumerLoader = requestingBundle.adapt(BundleWiring.class).getClassLoader(); - try { - LOG.debug("getService() from serviceFactory for {}", interfaceNames); - final List<Class<?>> interfaces = new ArrayList<Class<?>>(); - for (String ifaceName : interfaceNames) { - interfaces.add(consumerLoader.loadClass(ifaceName)); - } - Object proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() { - public Object run() { - Class<?>[] ifAr = interfaces.toArray(new Class[]{}); - return handler.importEndpoint(consumerLoader, consumerContext, ifAr, endpoint); - } - }); - - synchronized (this) { - serviceCounter++; - } - return proxy; - } catch (IntentUnsatisfiedException iue) { - LOG.info("Did not create proxy for {} because intent {} could not be satisfied", - interfaceNames, iue.getIntent()); - } catch (Exception e) { - LOG.warn("Problem creating a remote proxy for {}", interfaceNames, e); - } - return null; - } - - public void ungetService(Bundle requestingBundle, ServiceRegistration sreg, Object serviceObject) { - String[] interfaces = (String[])sreg.getReference().getProperty(org.osgi.framework.Constants.OBJECTCLASS); - LOG.info("Releasing a client object, interfaces: {}", Arrays.toString(interfaces)); - - synchronized (this) { - serviceCounter--; - LOG.debug("Services still provided by this ServiceFactory: {}", serviceCounter); - closeIfUnused(); - } - } - - public void setCloseable(boolean closeable) { - synchronized (this) { - this.closeable = closeable; - closeIfUnused(); - } - } - - private synchronized void closeIfUnused() { - if (serviceCounter <= 0 && closeable) { - importRegistration.closeAll(); - } - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/DistributionProviderTracker.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/DistributionProviderTracker.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/DistributionProviderTracker.java deleted file mode 100644 index 675fcc6..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/DistributionProviderTracker.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import java.util.Dictionary; -import java.util.Hashtable; - -import org.apache.cxf.dosgi.dsw.api.DistributionProvider; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.ServiceRegistration; -import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; -import org.osgi.util.tracker.ServiceTracker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings("rawtypes") -public class DistributionProviderTracker extends ServiceTracker<DistributionProvider, ServiceRegistration> { - private static final Logger LOG = LoggerFactory.getLogger(Activator.class); - - public DistributionProviderTracker(BundleContext context) { - super(context, DistributionProvider.class, null); - } - - @Override - public ServiceRegistration addingService(ServiceReference<DistributionProvider> reference) { - LOG.debug("RemoteServiceAdmin Implementation is starting up"); - DistributionProvider provider = context.getService(reference); - BundleContext apiContext = getAPIContext(); - RemoteServiceAdminCore rsaCore = new RemoteServiceAdminCore(context, - apiContext, - provider); - RemoteServiceadminFactory rsaf = new RemoteServiceadminFactory(rsaCore); - Dictionary<String, Object> props = new Hashtable<String, Object>(); - props.put("remote.intents.supported", reference.getProperty("remote.intents.supported")); - props.put("remote.configs.supported", reference.getProperty("remote.configs.supported")); - LOG.info("Registering RemoteServiceAdmin for provider " + provider.getClass().getName()); - return context.registerService(RemoteServiceAdmin.class.getName(), rsaf, props); - } - - protected BundleContext getAPIContext() { - Bundle apiBundle = FrameworkUtil.getBundle(DistributionProvider.class); - BundleContext apiContext = apiBundle.getBundleContext(); - return apiContext; - } - - @Override - public void removedService(ServiceReference<DistributionProvider> reference, - ServiceRegistration reg) { - LOG.debug("RemoteServiceAdmin Implementation is shutting down now"); - reg.unregister(); - super.removedService(reference, reg); - } - -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventAdminHelper.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventAdminHelper.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventAdminHelper.java deleted file mode 100644 index 4868efa..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventAdminHelper.java +++ /dev/null @@ -1,151 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import java.util.HashMap; -import java.util.Map; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.Version; -import org.osgi.service.event.Event; -import org.osgi.service.event.EventAdmin; -import org.osgi.service.remoteserviceadmin.EndpointDescription; -import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventAdminHelper { - - private static final Logger LOG = LoggerFactory.getLogger(EventAdminHelper.class); - - private BundleContext bctx; - - public EventAdminHelper(BundleContext bc) { - bctx = bc; - } - - private Event createEvent(Map<String, Object> props, String type) { - String topic = "org/osgi/service/remoteserviceadmin/" + type; - props.put("bundle", bctx.getBundle()); - props.put("bundle.id", bctx.getBundle().getBundleId()); - props.put("bundle.symbolicname", bctx.getBundle().getSymbolicName()); - - String version = (String)bctx.getBundle().getHeaders().get("Bundle-Version"); - Version v = version != null ? new Version(version) : Version.emptyVersion; - setIfNotNull(props, "bundle.version", v); - - return new Event(topic, props); - } - - public void notifyEventAdmin(RemoteServiceAdminEvent rsae) { - String topic = remoteServiceAdminEventTypeToString(rsae.getType()); - - Map<String, Object> props = new HashMap<String, Object>(); - setIfNotNull(props, "cause", rsae.getException()); - - EndpointDescription endpoint = null; - if (rsae.getImportReference() != null) { - endpoint = ((ImportRegistrationImpl)rsae.getImportReference()).getImportedEndpointAlways(); - setIfNotNull(props, "import.registration", endpoint); - } else if (rsae.getExportReference() != null) { - endpoint = rsae.getExportReference().getExportedEndpoint(); - setIfNotNull(props, "export.registration", endpoint); - } - - if (endpoint != null) { - setIfNotNull(props, "service.remote.id", endpoint.getServiceId()); - setIfNotNull(props, "service.remote.uuid", endpoint.getFrameworkUUID()); - setIfNotNull(props, "service.remote.uri", endpoint.getId()); - setIfNotNull(props, "objectClass", endpoint.getInterfaces().toArray()); - setIfNotNull(props, "service.imported.configs", endpoint.getConfigurationTypes()); - } - props.put("timestamp", System.currentTimeMillis()); - props.put("event", rsae); - - Event event = createEvent(props, topic); - notifyEventAdmins(topic, event); - } - - @SuppressWarnings({ - "rawtypes", "unchecked" - }) - private void notifyEventAdmins(String topic, Event event) { - ServiceReference[] refs = null; - try { - refs = bctx.getAllServiceReferences(EventAdmin.class.getName(), null); - } catch (InvalidSyntaxException e) { - LOG.error("Failed to get EventAdmin: " + e.getMessage(), e); - } - - if (refs != null) { - LOG.debug("Publishing event to {} EventAdmins; Topic:[{}]", refs.length, topic); - for (ServiceReference serviceReference : refs) { - EventAdmin eventAdmin = (EventAdmin) bctx.getService(serviceReference); - try { - eventAdmin.postEvent(event); - } finally { - if (eventAdmin != null) { - bctx.ungetService(serviceReference); - } - } - } - } - } - - private <K, V> void setIfNotNull(Map<K, V> map, K key, V val) { - if (val != null) { - map.put(key, val); - } - } - - private static String remoteServiceAdminEventTypeToString(int type) { - String retval; - switch (type) { - case RemoteServiceAdminEvent.EXPORT_ERROR: - retval = "EXPORT_ERROR"; - break; - case RemoteServiceAdminEvent.EXPORT_REGISTRATION: - retval = "EXPORT_REGISTRATION"; - break; - case RemoteServiceAdminEvent.EXPORT_UNREGISTRATION: - retval = "EXPORT_UNREGISTRATION"; - break; - case RemoteServiceAdminEvent.EXPORT_WARNING: - retval = "EXPORT_WARNING"; - break; - case RemoteServiceAdminEvent.IMPORT_ERROR: - retval = "IMPORT_ERROR"; - break; - case RemoteServiceAdminEvent.IMPORT_REGISTRATION: - retval = "IMPORT_REGISTRATION"; - break; - case RemoteServiceAdminEvent.IMPORT_UNREGISTRATION: - retval = "IMPORT_UNREGISTRATION"; - break; - case RemoteServiceAdminEvent.IMPORT_WARNING: - retval = "IMPORT_WARNING"; - break; - default: - retval = "UNKNOWN_EVENT"; - } - return retval; - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventProducer.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventProducer.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventProducer.java deleted file mode 100644 index 26a46ab..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/EventProducer.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import java.util.List; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.service.remoteserviceadmin.ExportRegistration; -import org.osgi.service.remoteserviceadmin.ImportRegistration; -import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; -import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventProducer { - - private static final Logger LOG = LoggerFactory.getLogger(EventProducer.class); - private final BundleContext bctx; - private final EventAdminHelper eaHelper; - - public EventProducer(BundleContext bc) { - bctx = bc; - eaHelper = new EventAdminHelper(bctx); - } - - protected void publishNotification(List<ExportRegistration> erl) { - for (ExportRegistration exportRegistration : erl) { - publishNotification(exportRegistration); - } - } - - protected void publishNotification(ExportRegistration er) { - int type = er.getException() == null - ? RemoteServiceAdminEvent.EXPORT_REGISTRATION - : RemoteServiceAdminEvent.EXPORT_ERROR; - notify(type, null, er); - } - - protected void publishNotification(ImportRegistration ir) { - int type = ir.getException() == null - ? RemoteServiceAdminEvent.IMPORT_REGISTRATION - : RemoteServiceAdminEvent.IMPORT_ERROR; - notify(type, ir, null); - } - - public void notifyRemoval(ExportRegistration er) { - notify(RemoteServiceAdminEvent.EXPORT_UNREGISTRATION, null, er); - } - - public void notifyRemoval(ImportRegistration ir) { - notify(RemoteServiceAdminEvent.IMPORT_UNREGISTRATION, ir, null); - } - - // only one of ir or er must be set, and the other must be null - private void notify(int type, ImportRegistration ir, ExportRegistration er) { - try { - RemoteServiceAdminEvent event = ir != null - ? new RemoteServiceAdminEvent(type, bctx.getBundle(), ir.getImportReference(), ir.getException()) - : new RemoteServiceAdminEvent(type, bctx.getBundle(), er.getExportReference(), er.getException()); - notifyListeners(event); - eaHelper.notifyEventAdmin(event); - } catch (IllegalStateException ise) { - LOG.debug("can't send notifications since bundle context is no longer valid"); - } - } - - @SuppressWarnings({ - "rawtypes", "unchecked" - }) - private void notifyListeners(RemoteServiceAdminEvent rsae) { - try { - ServiceReference[] listenerRefs = bctx.getServiceReferences( - RemoteServiceAdminListener.class.getName(), null); - if (listenerRefs != null) { - for (ServiceReference sref : listenerRefs) { - RemoteServiceAdminListener rsal = (RemoteServiceAdminListener)bctx.getService(sref); - if (rsal != null) { - try { - Bundle bundle = sref.getBundle(); - if (bundle != null) { - LOG.debug("notify RemoteServiceAdminListener {} of bundle {}", - rsal, bundle.getSymbolicName()); - rsal.remoteAdminEvent(rsae); - } - } finally { - bctx.ungetService(sref); - } - } - } - } - } catch (InvalidSyntaxException e) { - LOG.error(e.getMessage(), e); - } - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportReferenceImpl.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportReferenceImpl.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportReferenceImpl.java deleted file mode 100644 index 497aa9c..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportReferenceImpl.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import org.osgi.framework.ServiceReference; -import org.osgi.service.remoteserviceadmin.EndpointDescription; -import org.osgi.service.remoteserviceadmin.ExportReference; - -@SuppressWarnings("rawtypes") -public class ExportReferenceImpl implements ExportReference { - - private ServiceReference serviceReference; - private EndpointDescription endpoint; - - public ExportReferenceImpl(ServiceReference serviceReference, EndpointDescription endpoint) { - this.serviceReference = serviceReference; - this.endpoint = endpoint; - } - - public ExportReferenceImpl(ExportReference exportReference) { - this(exportReference.getExportedService(), exportReference.getExportedEndpoint()); - } - - public EndpointDescription getExportedEndpoint() { - return endpoint; - } - - public ServiceReference getExportedService() { - return serviceReference; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (endpoint == null ? 0 : endpoint.hashCode()); - result = prime * result + (serviceReference == null ? 0 : serviceReference.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - ExportReferenceImpl other = (ExportReferenceImpl) obj; - boolean ed = endpoint == null ? other.endpoint == null - : endpoint.equals(other.endpoint); - boolean sr = serviceReference == null ? other.serviceReference == null - : serviceReference.equals(other.serviceReference); - return ed && sr; - } - - synchronized void close() { - this.endpoint = null; - this.serviceReference = null; - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportRegistrationImpl.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportRegistrationImpl.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportRegistrationImpl.java deleted file mode 100644 index d80bd40..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ExportRegistrationImpl.java +++ /dev/null @@ -1,152 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import java.io.Closeable; -import java.io.IOException; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; - -import org.apache.cxf.dosgi.dsw.api.Endpoint; -import org.osgi.framework.ServiceReference; -import org.osgi.service.remoteserviceadmin.EndpointDescription; -import org.osgi.service.remoteserviceadmin.ExportReference; -import org.osgi.service.remoteserviceadmin.ExportRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings("rawtypes") -public class ExportRegistrationImpl implements ExportRegistration { - - private static final Logger LOG = LoggerFactory.getLogger(ExportRegistrationImpl.class); - - private final RemoteServiceAdminCore rsaCore; - private final ExportReferenceImpl exportReference; - private final Closeable server; - private final Throwable exception; - - private final ExportRegistrationImpl parent; - private int instanceCount; - private volatile boolean closed; - - private ExportRegistrationImpl(ExportRegistrationImpl parent, RemoteServiceAdminCore rsaCore, - ExportReferenceImpl exportReference, Closeable server, Throwable exception) { - this.parent = parent != null ? parent.parent : this; // a parent points to itself - this.parent.addInstance(); - this.rsaCore = rsaCore; - this.exportReference = exportReference; - this.server = server; - this.exception = exception; - } - - // create a clone of the provided ExportRegistrationImpl that is linked to it - public ExportRegistrationImpl(ExportRegistrationImpl parent) { - this(parent, parent.rsaCore, new ExportReferenceImpl(parent.exportReference), - parent.server, parent.exception); - } - - // create a new (parent) instance which was exported successfully with the given server - public ExportRegistrationImpl(ServiceReference sref, Endpoint endpoint, RemoteServiceAdminCore rsaCore) { - this(null, rsaCore, new ExportReferenceImpl(sref, endpoint.description()), endpoint, null); - } - - // create a new (parent) instance which failed to be exported with the given exception - public ExportRegistrationImpl(RemoteServiceAdminCore rsaCore, Throwable exception) { - this(null, rsaCore, null, null, exception); - } - - private void ensureParent() { - if (parent != this) { - throw new IllegalStateException("this method may only be called on the parent"); - } - } - - public ExportReference getExportReference() { - if (exportReference == null) { - throw new IllegalStateException(getException()); - } - return closed ? null : exportReference; - } - - public Throwable getException() { - return closed ? null : exception; - } - - public final void close() { - synchronized (this) { - if (closed) { - return; - } - closed = true; - } - - rsaCore.removeExportRegistration(this); - exportReference.close(); - parent.removeInstance(); - } - - private void addInstance() { - ensureParent(); - synchronized (this) { - instanceCount++; - } - } - - private void removeInstance() { - ensureParent(); - synchronized (this) { - instanceCount--; - if (instanceCount <= 0) { - LOG.debug("really closing ExportRegistration now!"); - - if (server != null) { - try { - server.close(); - } catch (IOException e) { - LOG.warn("Error closing ExportRegistration", e); - } - } - } - } - } - - @Override - public String toString() { - if (closed) { - return "ExportRegistration closed"; - } - EndpointDescription endpoint = getExportReference().getExportedEndpoint(); - ServiceReference serviceReference = getExportReference().getExportedService(); - String r = "EndpointDescription for ServiceReference " + serviceReference; - - r += "\n*** EndpointDescription: ****\n"; - if (endpoint == null) { - r += "---> NULL <---- \n"; - } else { - Set<Map.Entry<String, Object>> props = endpoint.getProperties().entrySet(); - for (Map.Entry<String, Object> entry : props) { - Object value = entry.getValue(); - r += entry.getKey() + " => " - + (value instanceof Object[] ? Arrays.toString((Object[]) value) : value) + "\n"; - } - } - return r; - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ImportRegistrationImpl.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ImportRegistrationImpl.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ImportRegistrationImpl.java deleted file mode 100644 index 2b896db..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/ImportRegistrationImpl.java +++ /dev/null @@ -1,230 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import java.util.ArrayList; -import java.util.List; - -import org.osgi.framework.ServiceReference; -import org.osgi.framework.ServiceRegistration; -import org.osgi.service.remoteserviceadmin.EndpointDescription; -import org.osgi.service.remoteserviceadmin.ImportReference; -import org.osgi.service.remoteserviceadmin.ImportRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings("rawtypes") -public class ImportRegistrationImpl implements ImportRegistration, ImportReference { - - private static final Logger LOG = LoggerFactory.getLogger(ImportRegistrationImpl.class); - - private volatile Throwable exception; - private volatile ServiceRegistration importedService; // used only in parent - private EndpointDescription endpoint; - private volatile ClientServiceFactory clientServiceFactory; - private RemoteServiceAdminCore rsaCore; - private boolean closed; - private boolean detached; // used only in parent - - private ImportRegistrationImpl parent; - private List<ImportRegistrationImpl> children; // used only in parent - - public ImportRegistrationImpl(Throwable ex) { - exception = ex; - initParent(); - } - - public ImportRegistrationImpl(EndpointDescription endpoint, RemoteServiceAdminCore rsac) { - this.endpoint = endpoint; - this.rsaCore = rsac; - initParent(); - } - - /** - * Creates a clone of the given parent instance. - */ - public ImportRegistrationImpl(ImportRegistrationImpl ir) { - // we always want a link to the parent... - parent = ir.getParent(); - exception = parent.getException(); - endpoint = parent.getImportedEndpointDescription(); - clientServiceFactory = parent.clientServiceFactory; - rsaCore = parent.rsaCore; - - parent.instanceAdded(this); - } - - private void initParent() { - parent = this; - children = new ArrayList<ImportRegistrationImpl>(1); - } - - private void ensureParent() { - if (parent != this) { - throw new IllegalStateException("this method may only be called on the parent"); - } - } - - /** - * Called on parent when a child is added. - * - * @param iri the child - */ - private synchronized void instanceAdded(ImportRegistrationImpl iri) { - ensureParent(); - children.add(iri); - } - - /** - * Called on parent when a child is closed. - * - * @param iri the child - */ - private void instanceClosed(ImportRegistrationImpl iri) { - ensureParent(); - synchronized (this) { - children.remove(iri); - if (!children.isEmpty() || detached || !closed) { - return; - } - detached = true; - } - - LOG.debug("really closing ImportRegistration now"); - - if (importedService != null) { - try { - importedService.unregister(); - } catch (IllegalStateException ise) { - LOG.debug("imported service is already unregistered"); - } - importedService = null; - } - if (clientServiceFactory != null) { - clientServiceFactory.setCloseable(true); - } - } - - public void close() { - LOG.debug("close() called"); - - synchronized (this) { - if (isInvalid()) { - return; - } - closed = true; - } - rsaCore.removeImportRegistration(this); - parent.instanceClosed(this); - } - - /** - * Closes all ImportRegistrations which share the same parent as this one. - */ - public void closeAll() { - if (this == parent) { - LOG.info("closing down all child ImportRegistrations"); - - // we must iterate over a copy of children since close() removes the child - // from the list (which would cause a ConcurrentModificationException) - for (ImportRegistrationImpl ir : copyChildren()) { - ir.close(); - } - this.close(); - } else { - parent.closeAll(); - } - } - - private List<ImportRegistrationImpl> copyChildren() { - synchronized (this) { - return new ArrayList<ImportRegistrationImpl>(children); - } - } - - public EndpointDescription getImportedEndpointDescription() { - return isInvalid() ? null : endpoint; - } - - @Override - public EndpointDescription getImportedEndpoint() { - return getImportedEndpointDescription(); - } - - @Override - public ServiceReference getImportedService() { - return isInvalid() || parent.importedService == null ? null : parent.importedService.getReference(); - } - - @Override - public ImportReference getImportReference() { - return this; - } - - @Override - public Throwable getException() { - return exception; - } - - public void setException(Throwable ex) { - exception = ex; - } - - private synchronized boolean isInvalid() { - return exception != null || closed; - } - - /** - * Sets the {@link ServiceRegistration} representing the locally - * registered {@link ClientServiceFactory} service which provides - * proxies to the remote imported service. It is set only on the parent. - * - * @param sreg the ServiceRegistration - */ - public void setImportedServiceRegistration(ServiceRegistration sreg) { - ensureParent(); - importedService = sreg; - } - - /** - * Sets the {@link ClientServiceFactory} which is the implementation - * of the locally registered service which provides proxies to the - * remote imported service. It is set only on the parent. - * - * @param csf the ClientServiceFactory - */ - public void setClientServiceFactory(ClientServiceFactory csf) { - ensureParent(); - clientServiceFactory = csf; - } - - public ImportRegistrationImpl getParent() { - return parent; - } - - /** - * Returns the imported endpoint even if this - * instance is closed or has an exception. - * - * @return the imported endpoint - */ - public EndpointDescription getImportedEndpointAlways() { - return endpoint; - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/PackageUtil.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/PackageUtil.java b/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/PackageUtil.java deleted file mode 100644 index effcef1..0000000 --- a/rsa/src/main/java/org/apache/cxf/dosgi/dsw/service/PackageUtil.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * 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.cxf.dosgi.dsw.service; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; -import org.osgi.service.packageadmin.ExportedPackage; -import org.osgi.service.packageadmin.PackageAdmin; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@SuppressWarnings("deprecation") -public final class PackageUtil { - - public static final Logger LOG = LoggerFactory.getLogger(PackageUtil.class); - - private PackageUtil() { - } - - /** - * Tries to retrieve the version of iClass via the PackageAdmin. - * - * @param iClass tThe interface for which the version should be found - * @param bc any valid BundleContext - * @return the version of the interface or "0.0.0" if no version information could be found or an error - * occurred during the retrieval - */ - public static String getVersion(Class<?> iClass, BundleContext bc) { - ServiceReference<PackageAdmin> paRef = bc.getServiceReference(PackageAdmin.class); - if (paRef != null) { - PackageAdmin pa = bc.getService(paRef); - try { - Bundle b = pa.getBundle(iClass); - if (b == null) { - LOG.info("Unable to find interface version for interface " + iClass.getName() - + ". Falling back to 0.0.0"); - return "0.0.0"; - } - LOG.debug("Interface source bundle: {}", b.getSymbolicName()); - - ExportedPackage[] ep = pa.getExportedPackages(b); - LOG.debug("Exported Packages of the source bundle: {}", (Object)ep); - - String pack = iClass.getPackage().getName(); - LOG.debug("Looking for Package: {}", pack); - if (ep != null) { - for (ExportedPackage p : ep) { - if (p != null - && pack.equals(p.getName())) { - LOG.debug("found package -> Version: {}", p.getVersion()); - return p.getVersion().toString(); - } - } - } - } finally { - if (pa != null) { - bc.ungetService(paRef); - } - } - } else { - LOG.error("Was unable to obtain the package admin service -> can't resolve interface versions"); - } - - LOG.info("Unable to find interface version for interface " + iClass.getName() - + ". Falling back to 0.0.0"); - return "0.0.0"; - } -}
