| /******************************************************************************* |
| * Copyright (c) 2010-2011 Composent, Inc. and others. All rights reserved. This |
| * program and the accompanying materials are made available under the terms of |
| * the Eclipse Public License v1.0 which accompanies this distribution, and is |
| * available at http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Composent, Inc. - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.ecf.internal.osgi.services.remoteserviceadmin; |
| |
| import java.util.ArrayList; |
| import java.util.Dictionary; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Properties; |
| import java.util.UUID; |
| |
| import javax.xml.parsers.SAXParserFactory; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.ecf.core.ContainerFactory; |
| import org.eclipse.ecf.core.ContainerTypeDescription; |
| import org.eclipse.ecf.core.IContainerManager; |
| import org.eclipse.ecf.core.util.LogHelper; |
| import org.eclipse.ecf.core.util.SystemLogService; |
| import org.eclipse.ecf.osgi.services.remoteserviceadmin.EndpointDescriptionLocator; |
| import org.eclipse.ecf.osgi.services.remoteserviceadmin.IServiceInfoFactory; |
| import org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin; |
| import org.eclipse.ecf.osgi.services.remoteserviceadmin.ServiceInfoFactory; |
| import org.eclipse.ecf.remoteservice.IRemoteServiceContainerAdapter; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleActivator; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.ServiceFactory; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.framework.Version; |
| import org.osgi.service.log.LogService; |
| import org.osgi.util.tracker.ServiceTracker; |
| import org.osgi.util.tracker.ServiceTrackerCustomizer; |
| |
| public class Activator implements BundleActivator { |
| |
| public static final String PLUGIN_ID = "org.eclipse.ecf.osgi.services.remoteserviceadmin"; //$NON-NLS-1$ |
| |
| private static BundleContext context; |
| private static Activator instance; |
| |
| public static BundleContext getContext() { |
| return context; |
| } |
| |
| public static Activator getDefault() { |
| return instance; |
| } |
| |
| public IContainerManager getContainerManager() { |
| return (IContainerManager) ContainerFactory.getDefault(); |
| } |
| |
| private ServiceRegistration remoteServiceAdminRegistration; |
| private Dictionary rsaProps; |
| private ServiceTracker<ContainerTypeDescription,ContainerTypeDescription> ctdTracker; |
| |
| private EndpointDescriptionLocator endpointDescriptionLocator; |
| private ServiceRegistration<?> iServiceInfoFactoryRegistration; |
| |
| // Logging |
| private ServiceTracker logServiceTracker = null; |
| private LogService logService = null; |
| private Object logServiceTrackerLock = new Object(); |
| // Sax parser |
| private Object saxParserFactoryTrackerLock = new Object(); |
| private ServiceTracker saxParserFactoryTracker; |
| |
| private static final String RSA_PROXY_BUNDLE_SYMBOLIC_ID = "org.eclipse.ecf.osgi.services.remoteserviceadmin.proxy"; //$NON-NLS-1$ |
| |
| private BundleContext proxyServiceFactoryBundleContext; |
| |
| private void initializeProxyServiceFactoryBundle() throws Exception { |
| // First, find proxy bundle |
| for (Bundle b : context.getBundles()) { |
| if (RSA_PROXY_BUNDLE_SYMBOLIC_ID.equals(b.getSymbolicName())) { |
| // first start it |
| b.start(); |
| // then get its bundle context |
| proxyServiceFactoryBundleContext = b.getBundleContext(); |
| } |
| } |
| if (proxyServiceFactoryBundleContext == null) |
| throw new IllegalStateException("RSA Proxy bundle (symbolic id=='" //$NON-NLS-1$ |
| + RSA_PROXY_BUNDLE_SYMBOLIC_ID |
| + "') cannot be found, so RSA cannot be started"); //$NON-NLS-1$ |
| } |
| |
| private void stopProxyServiceFactoryBundle() { |
| if (proxyServiceFactoryBundleContext != null) { |
| // stop it |
| try { |
| proxyServiceFactoryBundleContext.getBundle().stop(); |
| } catch (Exception e) { |
| // we don't care |
| } |
| proxyServiceFactoryBundleContext = null; |
| } |
| } |
| |
| public BundleContext getProxyServiceFactoryBundleContext() { |
| return proxyServiceFactoryBundleContext; |
| } |
| |
| private Map<Bundle, RemoteServiceAdmin> remoteServiceAdmins = new HashMap<Bundle, RemoteServiceAdmin>( |
| 1); |
| |
| private void removeSupportedConfigsAndIntents(ContainerTypeDescription ctd) { |
| String[] remoteConfigsSupported = (String[]) rsaProps.get( |
| org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_CONFIGS_SUPPORTED); |
| List<String> rcs = new ArrayList<String>(); |
| if (remoteConfigsSupported != null) |
| for(int i=0; i < remoteConfigsSupported.length; i++) rcs.add(remoteConfigsSupported[i]); |
| String[] remoteIntentsSupported = (String[]) rsaProps.get( |
| org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED); |
| List<String> ris = new ArrayList<String>(); |
| if (remoteIntentsSupported != null) |
| for(int i=0; i < remoteIntentsSupported.length; i++) ris.add(remoteIntentsSupported[i]); |
| |
| String[] descSupportedConfigs = ctd.getSupportedConfigs(); |
| if (descSupportedConfigs != null) { |
| for (int j = 0; j < descSupportedConfigs.length; j++) |
| rcs.remove(descSupportedConfigs[j]); |
| String[] descSupportedIntents = ctd.getSupportedIntents(); |
| for (int j = 0; j < descSupportedIntents.length; j++) |
| ris.remove(descSupportedIntents); |
| } |
| // set rsaProps to new values |
| rsaProps.put(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_CONFIGS_SUPPORTED, rcs.toArray(new String[rcs.size()])); |
| rsaProps.put(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED, ris.toArray(new String[ris.size()])); |
| } |
| |
| void addSupportedConfigsAndIntents(ContainerTypeDescription desc) { |
| // Get the existing remoteConfigsSupported from rsaProps |
| String[] remoteConfigsSupported = (String[]) rsaProps.get( |
| org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_CONFIGS_SUPPORTED); |
| // Add all the existing to rcs list |
| List<String> rcs = new ArrayList<String>(); |
| if (remoteConfigsSupported != null) |
| for(int i=0; i < remoteConfigsSupported.length; i++) rcs.add(remoteConfigsSupported[i]); |
| // Get the existing remoteIntentsSupported from rsaProps |
| String[] remoteIntentsSupported = (String[]) rsaProps.get( |
| org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED); |
| // Add all the existing to ris list |
| List<String> ris = new ArrayList<String>(); |
| if (remoteIntentsSupported != null) |
| for(int i=0; i < remoteIntentsSupported.length; i++) ris.add(remoteIntentsSupported[i]); |
| |
| // Get the supported configs from the given description |
| String[] descSupportedConfigs = desc.getSupportedConfigs(); |
| |
| if (descSupportedConfigs != null) { |
| // Add all supported configs...as long as they are not already present |
| for (int j = 0; j < descSupportedConfigs.length; j++) |
| if (!rcs.contains(descSupportedConfigs[j])) rcs.add(descSupportedConfigs[j]); |
| // Get supported intents |
| String[] descSupportedIntents = desc.getSupportedIntents(); |
| // Add them all |
| for (int j = 0; j < descSupportedIntents.length; j++) |
| ris.add(descSupportedIntents[j]); |
| } |
| // set rsaProps to new values |
| rsaProps.put(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_CONFIGS_SUPPORTED, rcs.toArray(new String[rcs.size()])); |
| rsaProps.put(org.osgi.service.remoteserviceadmin.RemoteConstants.REMOTE_INTENTS_SUPPORTED, ris.toArray(new String[ris.size()])); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext |
| * ) |
| */ |
| public void start(BundleContext bundleContext) throws Exception { |
| Activator.context = bundleContext; |
| Activator.instance = this; |
| // initialize the RSA proxy service factory bundle...so that we |
| // can get/use *that bundle's BundleContext for registering the |
| // proxy ServiceFactory. |
| // See osgi-dev thread here for info about this |
| // approach/using the ServiceFactory extender approach for this purpose: |
| // https://mail.osgi.org/pipermail/osgi-dev/2011-February/003000.html |
| initializeProxyServiceFactoryBundle(); |
| |
| // make remote service admin available |
| rsaProps = new Properties(); |
| rsaProps.put(RemoteServiceAdmin.SERVICE_PROP, new Boolean(true)); |
| |
| IContainerManager containerManager = getContainerManager(); |
| Assert.isNotNull(containerManager, |
| "Container manager service must be present to start ECF Remote Service Admin"); //$NON-NLS-1$ |
| |
| ContainerTypeDescription[] remoteServiceDescriptions = containerManager |
| .getContainerFactory().getDescriptionsForContainerAdapter( |
| IRemoteServiceContainerAdapter.class); |
| // The following adds the standard supported configs and supported intents |
| // values for all remote service descriptions to rsaProps |
| for (int i = 0; i < remoteServiceDescriptions.length; i++) |
| addSupportedConfigsAndIntents(remoteServiceDescriptions[i]); |
| |
| // Register Remote Service Admin factory, with rsaProps |
| remoteServiceAdminRegistration = context.registerService( |
| org.osgi.service.remoteserviceadmin.RemoteServiceAdmin.class |
| .getName(), new ServiceFactory() { |
| public Object getService(Bundle bundle, |
| ServiceRegistration registration) { |
| RemoteServiceAdmin result = null; |
| synchronized (remoteServiceAdmins) { |
| RemoteServiceAdmin rsa = remoteServiceAdmins |
| .get(bundle); |
| if (rsa == null) { |
| rsa = new RemoteServiceAdmin(bundle); |
| remoteServiceAdmins.put(bundle, rsa); |
| } |
| result = rsa; |
| } |
| return result; |
| } |
| |
| public void ungetService(Bundle bundle, |
| ServiceRegistration registration, Object service) { |
| synchronized (remoteServiceAdmins) { |
| RemoteServiceAdmin rsa = remoteServiceAdmins |
| .remove(bundle); |
| if (rsa != null) |
| rsa.close(); |
| } |
| } |
| }, (Dictionary) rsaProps); |
| |
| ctdTracker = new ServiceTracker<ContainerTypeDescription,ContainerTypeDescription>(context,ContainerTypeDescription.class,new ServiceTrackerCustomizer<ContainerTypeDescription,ContainerTypeDescription>() { |
| public ContainerTypeDescription addingService( |
| ServiceReference<ContainerTypeDescription> reference) { |
| ContainerTypeDescription ctd = null; |
| if (reference != null && context != null) { |
| ctd = context.getService(reference); |
| if (ctd != null) { |
| // Add any new supported configs to rsaProps |
| addSupportedConfigsAndIntents(ctd); |
| if (remoteServiceAdminRegistration != null) |
| // Set the new properties for remoteServiceRegistration |
| remoteServiceAdminRegistration.setProperties(rsaProps); |
| } |
| } |
| return ctd; |
| } |
| |
| public void modifiedService( |
| ServiceReference<ContainerTypeDescription> reference, |
| ContainerTypeDescription service) { |
| } |
| |
| public void removedService( |
| ServiceReference<ContainerTypeDescription> reference, |
| ContainerTypeDescription service) { |
| if (remoteServiceAdminRegistration != null && service != null) { |
| // Remove supported configs and intents from rsaProps |
| removeSupportedConfigsAndIntents(service); |
| // Reset properties for remoteServiceAdmin |
| remoteServiceAdminRegistration.setProperties(rsaProps); |
| } |
| } |
| }); |
| ctdTracker.open(); |
| |
| // create endpoint description locator |
| endpointDescriptionLocator = new EndpointDescriptionLocator(context); |
| // create and register endpoint description advertiser |
| final Properties properties = new Properties(); |
| properties.put(Constants.SERVICE_RANKING, |
| new Integer(Integer.MIN_VALUE)); |
| iServiceInfoFactoryRegistration = context.registerService( |
| IServiceInfoFactory.class.getName(), |
| new ServiceInfoFactory(), (Dictionary) properties); |
| |
| // start endpointDescriptionLocator |
| endpointDescriptionLocator.start(); |
| } |
| |
| private void clearRSAs() { |
| synchronized (remoteServiceAdmins) { |
| for (Iterator<Entry<Bundle, RemoteServiceAdmin>> i = remoteServiceAdmins |
| .entrySet().iterator(); i.hasNext();) { |
| Entry<Bundle, RemoteServiceAdmin> entry = i.next(); |
| RemoteServiceAdmin rsa = entry.getValue(); |
| rsa.close(); |
| i.remove(); |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) |
| */ |
| public void stop(BundleContext bundleContext) throws Exception { |
| if (endpointDescriptionLocator != null) { |
| endpointDescriptionLocator.close(); |
| endpointDescriptionLocator = null; |
| } |
| if (ctdTracker != null) { |
| ctdTracker.close(); |
| ctdTracker = null; |
| } |
| if (remoteServiceAdminRegistration != null) { |
| remoteServiceAdminRegistration.unregister(); |
| remoteServiceAdminRegistration = null; |
| } |
| clearRSAs(); |
| if (iServiceInfoFactoryRegistration != null) { |
| iServiceInfoFactoryRegistration.unregister(); |
| iServiceInfoFactoryRegistration = null; |
| } |
| synchronized (saxParserFactoryTrackerLock) { |
| if (saxParserFactoryTracker != null) { |
| saxParserFactoryTracker.close(); |
| saxParserFactoryTracker = null; |
| } |
| } |
| synchronized (logServiceTrackerLock) { |
| if (logServiceTracker != null) { |
| logServiceTracker.close(); |
| logServiceTracker = null; |
| logService = null; |
| } |
| } |
| stopProxyServiceFactoryBundle(); |
| Activator.context = null; |
| Activator.instance = null; |
| } |
| |
| public boolean isOldEquinox() { |
| if (context == null) |
| return false; |
| Bundle systemBundle = context.getBundle(0); |
| String systemBSN = systemBundle.getSymbolicName(); |
| if ("org.eclipse.osgi".equals(systemBSN)) { //$NON-NLS-1$ |
| Version fixedVersion = new Version("3.7.0"); //$NON-NLS-1$ |
| // running on equinox; check the version |
| Version systemVersion = systemBundle.getVersion(); |
| if (systemVersion.compareTo(fixedVersion) < 0) |
| return true; |
| } |
| return false; |
| } |
| |
| public String getFrameworkUUID() { |
| if (context == null) |
| return null; |
| // code get and set the framework uuid property as specified in |
| // r2.enterprise.pdf pg 297 |
| synchronized ("org.osgi.framework.uuid") { //$NON-NLS-1$ |
| String result = context.getProperty("org.osgi.framework.uuid"); //$NON-NLS-1$ |
| if (result == null) { |
| UUID newUUID = UUID.randomUUID(); |
| result = newUUID.toString(); |
| System.setProperty("org.osgi.framework.uuid", //$NON-NLS-1$ |
| newUUID.toString()); |
| } |
| return result; |
| } |
| } |
| |
| public SAXParserFactory getSAXParserFactory() { |
| if (instance == null) |
| return null; |
| synchronized (saxParserFactoryTrackerLock) { |
| if (saxParserFactoryTracker == null) { |
| saxParserFactoryTracker = new ServiceTracker(context, |
| SAXParserFactory.class.getName(), null); |
| saxParserFactoryTracker.open(); |
| } |
| return (SAXParserFactory) saxParserFactoryTracker.getService(); |
| } |
| } |
| |
| public LogService getLogService() { |
| if (context == null) |
| return null; |
| synchronized (logServiceTrackerLock) { |
| if (logServiceTracker == null) { |
| logServiceTracker = new ServiceTracker(context, |
| LogService.class.getName(), null); |
| logServiceTracker.open(); |
| } |
| logService = (LogService) logServiceTracker.getService(); |
| if (logService == null) |
| logService = new SystemLogService(PLUGIN_ID); |
| return logService; |
| } |
| } |
| |
| public void log(IStatus status) { |
| if (logService == null) |
| logService = getLogService(); |
| if (logService != null) |
| logService.log(null, LogHelper.getLogCode(status), |
| LogHelper.getLogMessage(status), status.getException()); |
| } |
| |
| public void log(ServiceReference sr, IStatus status) { |
| log(sr, LogHelper.getLogCode(status), LogHelper.getLogMessage(status), |
| status.getException()); |
| } |
| |
| public void log(ServiceReference sr, int level, String message, Throwable t) { |
| if (logService == null) |
| logService = getLogService(); |
| if (logService != null) |
| logService.log(sr, level, message, t); |
| } |
| |
| } |