From: <mwl...@us...> - 2008-03-21 17:40:26
|
Revision: 676 http://cishell.svn.sourceforge.net/cishell/?rev=676&view=rev Author: mwlinnem Date: 2008-03-21 10:39:47 -0700 (Fri, 21 Mar 2008) Log Message: ----------- Initial import. Preference Service needs this. Added Paths: ----------- branches/user_prefs/org.eclipse.equinox.cm/.classpath branches/user_prefs/org.eclipse.equinox.cm/.cvsignore branches/user_prefs/org.eclipse.equinox.cm/.project branches/user_prefs/org.eclipse.equinox.cm/.settings/ branches/user_prefs/org.eclipse.equinox.cm/META-INF/ branches/user_prefs/org.eclipse.equinox.cm/META-INF/MANIFEST.MF branches/user_prefs/org.eclipse.equinox.cm/about.html branches/user_prefs/org.eclipse.equinox.cm/build.properties branches/user_prefs/org.eclipse.equinox.cm/plugin.properties branches/user_prefs/org.eclipse.equinox.cm/src/ branches/user_prefs/org.eclipse.equinox.cm/src/org/ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/Activator.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminImpl.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationDictionary.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationEventAdapter.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationImpl.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationStore.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/EventDispatcher.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/LogTracker.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceTracker.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/PluginManager.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/SerializedTaskQueue.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/reliablefile/ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/reliablefile/ReliableFile.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/reliablefile/ReliableFileInputStream.java branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/reliablefile/ReliableFileOutputStream.java Added: branches/user_prefs/org.eclipse.equinox.cm/.classpath =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/.classpath (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/.classpath 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/OSGi%Minimum-1.1"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> Property changes on: branches/user_prefs/org.eclipse.equinox.cm/.classpath ___________________________________________________________________ Name: svn:executable + * Added: branches/user_prefs/org.eclipse.equinox.cm/.cvsignore =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/.cvsignore (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/.cvsignore 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1 @@ +bin Property changes on: branches/user_prefs/org.eclipse.equinox.cm/.cvsignore ___________________________________________________________________ Name: svn:executable + * Added: branches/user_prefs/org.eclipse.equinox.cm/.project =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/.project (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/.project 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.equinox.cm</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> Property changes on: branches/user_prefs/org.eclipse.equinox.cm/.project ___________________________________________________________________ Name: svn:executable + * Added: branches/user_prefs/org.eclipse.equinox.cm/META-INF/MANIFEST.MF =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/META-INF/MANIFEST.MF (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/META-INF/MANIFEST.MF 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %bundleName +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Bundle-SymbolicName: org.eclipse.equinox.cm +Bundle-Version: 1.0.0.qualifier +Bundle-Activator: org.eclipse.equinox.internal.cm.Activator +Import-Package: org.osgi.framework;version="1.3.0", + org.osgi.service.cm;version="1.2.0", + org.osgi.service.log;version="1.3.0", + org.osgi.service.event;version="1.0"; resolution:=optional, + org.osgi.util.tracker;version="1.3.1" +Export-Package: org.eclipse.equinox.internal.cm;x-internal:=true, + org.eclipse.equinox.internal.cm.reliablefile;x-internal:=true +Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.1, + CDC-1.0/Foundation-1.0, + J2SE-1.3 Property changes on: branches/user_prefs/org.eclipse.equinox.cm/META-INF/MANIFEST.MF ___________________________________________________________________ Name: svn:executable + * Added: branches/user_prefs/org.eclipse.equinox.cm/about.html =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/about.html (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/about.html 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>January 30, 2007</p> +<h3>License</h3> + +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> + +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p> + +</body> +</html> \ No newline at end of file Property changes on: branches/user_prefs/org.eclipse.equinox.cm/about.html ___________________________________________________________________ Name: svn:executable + * Added: branches/user_prefs/org.eclipse.equinox.cm/build.properties =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/build.properties (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/build.properties 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + about.html,\ + plugin.properties +src.includes = about.html Property changes on: branches/user_prefs/org.eclipse.equinox.cm/build.properties ___________________________________________________________________ Name: svn:executable + * Added: branches/user_prefs/org.eclipse.equinox.cm/plugin.properties =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/plugin.properties (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/plugin.properties 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation 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: +# IBM Corporation - initial API and implementation +############################################################################### +bundleName = Configuration Admin (Incubation) +providerName = Eclipse.org Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/Activator.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/Activator.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/Activator.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 Cognos Incorporated, IBM Corporation + * 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: + * Cognos Incorporated - initial API and implementation + * Chris Aniszczyk <zx...@us...> - bug 209294 + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import org.osgi.framework.*; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * Activator start the ConfigurationAdminFactory but also handles passing in the Service + * Registration needed by Asynch threads. Asynch threads are controlled by ConfigurationAdminFactory + * start and stop. It requires some care to handle pending events as the service is registered before + * activating the threads. (see EventDispatcher) + */ +public class Activator implements BundleActivator { + private static final String EVENT_ADMIN_CLASS = "org.osgi.service.event.EventAdmin"; //$NON-NLS-1$ + private LogTracker logTracker; + private ServiceRegistration registration; + private ConfigurationAdminFactory factory; + private ConfigurationEventAdapter eventAdapter; + private static BundleContext bundleContext; + + private static synchronized void setBundleContext(BundleContext context) { + bundleContext = context; + } + + public static synchronized String getProperty(String key) { + if (bundleContext != null) + return bundleContext.getProperty(key); + + return null; + } + + public void start(BundleContext context) throws Exception { + setBundleContext(context); + logTracker = new LogTracker(context, System.err); + logTracker.open(); + if (checkEventAdmin()) { + eventAdapter = new ConfigurationEventAdapter(context); + eventAdapter.start(); + } + factory = new ConfigurationAdminFactory(context, logTracker); + factory.start(); + context.addBundleListener(factory); + registration = context.registerService(ConfigurationAdmin.class.getName(), factory, null); + } + + public void stop(BundleContext context) throws Exception { + registration.unregister(); + registration = null; + context.removeBundleListener(factory); + factory.stop(); + factory = null; + if (eventAdapter != null) { + eventAdapter.stop(); + eventAdapter = null; + } + logTracker.close(); + logTracker = null; + setBundleContext(null); + } + + private static boolean checkEventAdmin() { + // cannot support scheduling without the event admin package + try { + Class.forName(EVENT_ADMIN_CLASS); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } +} Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminFactory.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.security.Permission; +import java.util.Dictionary; +import org.osgi.framework.*; +import org.osgi.service.cm.ConfigurationPermission; +import org.osgi.service.log.LogService; + +/** + * ConfigurationAdminFactory provides a Configuration Admin ServiceFactory but more significantly + * launches the whole implementation. + */ + +public class ConfigurationAdminFactory implements ServiceFactory, BundleListener { + + private final Permission configurationPermission = new ConfigurationPermission("*", ConfigurationPermission.CONFIGURE); //$NON-NLS-1$ + private final EventDispatcher eventDispatcher; + private final PluginManager pluginManager; + private final LogService log; + private final ManagedServiceTracker managedServiceTracker; + private final ManagedServiceFactoryTracker managedServiceFactoryTracker; + private final ConfigurationStore configurationStore; + + public ConfigurationAdminFactory(BundleContext context, LogService log) { + this.log = log; + configurationStore = new ConfigurationStore(this, context); + eventDispatcher = new EventDispatcher(context, log); + pluginManager = new PluginManager(context); + managedServiceTracker = new ManagedServiceTracker(this, configurationStore, context); + managedServiceFactoryTracker = new ManagedServiceFactoryTracker(this, configurationStore, context); + } + + void start() { + eventDispatcher.start(); + pluginManager.start(); + managedServiceTracker.open(); + managedServiceFactoryTracker.open(); + } + + void stop() { + managedServiceTracker.close(); + managedServiceFactoryTracker.close(); + eventDispatcher.stop(); + pluginManager.stop(); + } + + public Object getService(Bundle bundle, ServiceRegistration registration) { + ServiceReference reference = registration.getReference(); + eventDispatcher.setServiceReference(reference); + return new ConfigurationAdminImpl(this, configurationStore, bundle); + } + + public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { + // do nothing + } + + public void bundleChanged(BundleEvent event) { + if (event.getType() == BundleEvent.UNINSTALLED) + configurationStore.unbindConfigurations(event.getBundle()); + } + + public void checkConfigurationPermission() throws SecurityException { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(configurationPermission); + } + + void log(int level, String message) { + log.log(level, message); + } + + void log(int level, String message, Throwable exception) { + log.log(level, message, exception); + } + + void dispatchEvent(int type, String factoryPid, String pid) { + eventDispatcher.dispatchEvent(type, factoryPid, pid); + } + + void notifyConfigurationUpdated(ConfigurationImpl config, boolean isFactory) { + if (isFactory) + managedServiceFactoryTracker.notifyUpdated(config); + else + managedServiceTracker.notifyUpdated(config); + } + + void notifyConfigurationDeleted(ConfigurationImpl config, boolean isFactory) { + if (isFactory) + managedServiceFactoryTracker.notifyDeleted(config); + else + managedServiceTracker.notifyDeleted(config); + } + + void modifyConfiguration(ServiceReference reference, Dictionary properties) { + pluginManager.modifyConfiguration(reference, properties); + } +} \ No newline at end of file Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminImpl.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminImpl.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationAdminImpl.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.io.IOException; +import org.osgi.framework.*; +import org.osgi.service.cm.Configuration; +import org.osgi.service.cm.ConfigurationAdmin; + +/** + * ConfigurationAdminImpl provides the ConfigurationAdmin service implementation + */ +class ConfigurationAdminImpl implements ConfigurationAdmin { + + private final ConfigurationAdminFactory configurationAdminFactory; + private final Bundle bundle; + private final ConfigurationStore configurationStore; + + public ConfigurationAdminImpl(ConfigurationAdminFactory configurationAdminFactory, ConfigurationStore configurationStore, Bundle bundle) { + this.configurationAdminFactory = configurationAdminFactory; + this.configurationStore = configurationStore; + this.bundle = bundle; + } + + public Configuration createFactoryConfiguration(String factoryPid) throws IOException { + checkPID(factoryPid); + return configurationStore.createFactoryConfiguration(factoryPid, bundle.getLocation()); + } + + public Configuration createFactoryConfiguration(String factoryPid, String location) throws IOException { + checkPID(factoryPid); + this.configurationAdminFactory.checkConfigurationPermission(); + return configurationStore.createFactoryConfiguration(factoryPid, location); + } + + public Configuration getConfiguration(String pid) throws IOException { + checkPID(pid); + Configuration config = configurationStore.getConfiguration(pid, bundle.getLocation()); + if (config.getBundleLocation() != null && !config.getBundleLocation().equals(bundle.getLocation())) + this.configurationAdminFactory.checkConfigurationPermission(); + return config; + } + + public Configuration getConfiguration(String pid, String location) throws IOException { + checkPID(pid); + this.configurationAdminFactory.checkConfigurationPermission(); + return configurationStore.getConfiguration(pid, location); + } + + public Configuration[] listConfigurations(String filterString) throws IOException, InvalidSyntaxException { + if (filterString == null) + filterString = "(" + Constants.SERVICE_PID + "=*)"; //$NON-NLS-1$ //$NON-NLS-2$ + + try { + this.configurationAdminFactory.checkConfigurationPermission(); + } catch (SecurityException e) { + filterString = "(&(" + ConfigurationAdmin.SERVICE_BUNDLELOCATION + "=" + bundle.getLocation() + ")" + filterString + ")"; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ + } + return configurationStore.listConfigurations(FrameworkUtil.createFilter(filterString)); + } + + private void checkPID(String pid) { + if (pid == null) + throw new IllegalArgumentException("PID cannot be null"); //$NON-NLS-1$ + } +} \ No newline at end of file Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationDictionary.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationDictionary.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationDictionary.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; +import java.util.Vector; +import java.util.Map.Entry; + +/** + * ConfigurationDictionary holds the actual configuration data and meets the various comparison + * requirements of the Configuration Admin Service specification. + */ + +public class ConfigurationDictionary extends Dictionary implements Serializable { + + private static final long serialVersionUID = -3583299578203095532L; + private static final Collection simples = Arrays.asList(new Class[] {String.class, Integer.class, Long.class, Float.class, Double.class, Byte.class, Short.class, Character.class, Boolean.class}); + private static final Collection simpleArrays = Arrays.asList(new Class[] {String[].class, Integer[].class, Long[].class, Float[].class, Double[].class, Byte[].class, Short[].class, Character[].class, Boolean[].class}); + private static final Collection primitiveArrays = Arrays.asList(new Class[] {long[].class, int[].class, short[].class, char[].class, byte[].class, double[].class, float[].class, boolean[].class}); + + static class CaseInsensitiveStringComparator implements Comparator, Serializable { + private static final long serialVersionUID = 6501536810492374044L; + + public int compare(Object o1, Object o2) { + return ((String) o1).compareToIgnoreCase((String) o2); + } + } + + protected final Map configurationProperties = Collections.synchronizedMap(new TreeMap(new CaseInsensitiveStringComparator())); + + private static void validateValue(Object value) { + Class clazz = value.getClass(); + + // Is it in the set of simple types + if (simples.contains(clazz)) + return; + + // Is it an array of primitives or simples + if (simpleArrays.contains(clazz) || primitiveArrays.contains(clazz)) + return; + + // Is it a vector of simples + if (clazz == Vector.class) { + Vector valueVector = (Vector) value; + for (Iterator it = valueVector.iterator(); it.hasNext();) { + Class containedClazz = it.next().getClass(); + if (!simples.contains(containedClazz)) { + throw new IllegalArgumentException(containedClazz.getName() + " in " + Vector.class.getName()); //$NON-NLS-1$ + } + } + return; + } + throw new IllegalArgumentException(clazz.getName()); + } + + public Enumeration elements() { + return new Enumeration() { + final Iterator valuesIterator = configurationProperties.values().iterator(); + + public boolean hasMoreElements() { + return valuesIterator.hasNext(); + } + + public Object nextElement() { + return valuesIterator.next(); + } + }; + } + + public Object get(Object key) { + if (key == null) + throw new NullPointerException(); + return configurationProperties.get(key); + } + + public boolean isEmpty() { + return configurationProperties.isEmpty(); + } + + public Enumeration keys() { + return new Enumeration() { + Iterator keysIterator = configurationProperties.keySet().iterator(); + + public boolean hasMoreElements() { + return keysIterator.hasNext(); + } + + public Object nextElement() { + return keysIterator.next(); + } + }; + } + + public Object put(Object key, Object value) { + if (key == null || value == null) + throw new NullPointerException(); + + // Will throw an illegal argument exception if not a valid configuration property type + validateValue(value); + + return configurationProperties.put(key, value); + } + + public Object remove(Object key) { + if (key == null) + throw new NullPointerException(); + return configurationProperties.remove(key); + } + + public int size() { + return configurationProperties.size(); + } + + ConfigurationDictionary copy() { + ConfigurationDictionary result = new ConfigurationDictionary(); + for (Iterator it = configurationProperties.entrySet().iterator(); it.hasNext();) { + Entry entry = (Entry) it.next(); + Object key = entry.getKey(); + Object value = entry.getValue(); + if (value.getClass().isArray()) { + int arrayLength = Array.getLength(value); + Object copyOfArray = Array.newInstance(value.getClass().getComponentType(), arrayLength); + System.arraycopy(value, 0, copyOfArray, 0, arrayLength); + result.configurationProperties.put(key, copyOfArray); + } else if (value instanceof Vector) + result.configurationProperties.put(key, ((Vector) value).clone()); + else + result.configurationProperties.put(key, value); + } + return result; + } +} Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationEventAdapter.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationEventAdapter.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationEventAdapter.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.util.Hashtable; +import org.osgi.framework.*; +import org.osgi.service.cm.ConfigurationEvent; +import org.osgi.service.cm.ConfigurationListener; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; +import org.osgi.util.tracker.ServiceTracker; + +public class ConfigurationEventAdapter implements ConfigurationListener { + // constants for Event topic substring + public static final String TOPIC = "org/osgi/service/cm/ConfigurationEvent"; //$NON-NLS-1$ + public static final char TOPIC_SEPARATOR = '/'; + // constants for Event types + public static final String CM_UPDATED = "CM_UPDATED"; //$NON-NLS-1$ + public static final String CM_DELETED = "CM_DELETED"; //$NON-NLS-1$ + // constants for Event properties + public static final String CM_FACTORY_PID = "cm.factoryPid"; //$NON-NLS-1$ + public static final String CM_PID = "cm.pid"; //$NON-NLS-1$ + public static final String SERVICE = "service"; //$NON-NLS-1$ + public static final String SERVICE_ID = "service.id"; //$NON-NLS-1$ + public static final String SERVICE_OBJECTCLASS = "service.objectClass"; //$NON-NLS-1$ + public static final String SERVICE_PID = "service.pid"; //$NON-NLS-1$ + + private final BundleContext context; + private ServiceRegistration configListenerRegistration; + private final ServiceTracker eventAdminTracker; + + public ConfigurationEventAdapter(BundleContext context) { + this.context = context; + eventAdminTracker = new ServiceTracker(context, EventAdmin.class.getName(), null); + } + + public void start() throws Exception { + eventAdminTracker.open(); + configListenerRegistration = context.registerService(ConfigurationListener.class.getName(), this, null); + } + + public void stop() throws Exception { + configListenerRegistration.unregister(); + configListenerRegistration = null; + eventAdminTracker.close(); + } + + public void configurationEvent(ConfigurationEvent event) { + EventAdmin eventAdmin = (EventAdmin) eventAdminTracker.getService(); + if (eventAdmin == null) { + return; + } + String typename = null; + switch (event.getType()) { + case ConfigurationEvent.CM_UPDATED : + typename = CM_UPDATED; + break; + case ConfigurationEvent.CM_DELETED : + typename = CM_DELETED; + break; + default : // do nothing + return; + } + String topic = TOPIC + TOPIC_SEPARATOR + typename; + ServiceReference ref = event.getReference(); + if (ref == null) { + throw new RuntimeException("ServiceEvent.getServiceReference() is null"); //$NON-NLS-1$ + } + Hashtable properties = new Hashtable(); + properties.put(CM_PID, event.getPid()); + if (event.getFactoryPid() != null) { + properties.put(CM_FACTORY_PID, event.getFactoryPid()); + } + putServiceReferenceProperties(properties, ref); + Event convertedEvent = new Event(topic, properties); + eventAdmin.postEvent(convertedEvent); + } + + public void putServiceReferenceProperties(Hashtable properties, ServiceReference ref) { + properties.put(SERVICE, ref); + properties.put(SERVICE_ID, ref.getProperty(org.osgi.framework.Constants.SERVICE_ID)); + Object o = ref.getProperty(org.osgi.framework.Constants.SERVICE_PID); + if ((o != null) && (o instanceof String)) { + properties.put(SERVICE_PID, o); + } + Object o2 = ref.getProperty(org.osgi.framework.Constants.OBJECTCLASS); + if ((o2 != null) && (o2 instanceof String[])) { + properties.put(SERVICE_OBJECTCLASS, o2); + } + } +} Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationImpl.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationImpl.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationImpl.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,286 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Enumeration; +import org.osgi.framework.Bundle; +import org.osgi.framework.Constants; +import org.osgi.service.cm.*; + +/** + * ConfigurationImpl provides the Configuration implementation. + * The lock and unlock methods are used for synchronization. Operations outside of + * ConfigurationImpl that expect to have control of the lock should call checkLocked + */ +class ConfigurationImpl implements Configuration { + + private final ConfigurationAdminFactory configurationAdminFactory; + private final ConfigurationStore configurationStore; + /** @GuardedBy this*/ + private String bundleLocation; + private final String factoryPid; + private final String pid; + private ConfigurationDictionary dictionary; + /** @GuardedBy this*/ + private boolean deleted = false; + /** @GuardedBy this*/ + private Bundle boundBundle; + /** @GuardedBy this*/ + private int lockedCount = 0; + /** @GuardedBy this*/ + private Thread lockHolder = null; + + public ConfigurationImpl(ConfigurationAdminFactory configurationAdminFactory, ConfigurationStore configurationStore, String factoryPid, String pid, String bundleLocation) { + this.configurationAdminFactory = configurationAdminFactory; + this.configurationStore = configurationStore; + this.factoryPid = factoryPid; + this.pid = pid; + this.bundleLocation = bundleLocation; + } + + public ConfigurationImpl(ConfigurationAdminFactory configurationAdminFactory, ConfigurationStore configurationStore, Dictionary dictionary) { + this.configurationAdminFactory = configurationAdminFactory; + this.configurationStore = configurationStore; + pid = (String) dictionary.get(Constants.SERVICE_PID); + factoryPid = (String) dictionary.get(ConfigurationAdmin.SERVICE_FACTORYPID); + bundleLocation = (String) dictionary.get(ConfigurationAdmin.SERVICE_BUNDLELOCATION); + updateDictionary(dictionary); + } + + protected synchronized void lock() { + Thread current = Thread.currentThread(); + if (lockHolder != current) { + boolean interrupted = false; + try { + while (lockedCount != 0) + try { + wait(); + } catch (InterruptedException e) { + // although we don't handle an interrupt we should still + // save and restore the interrupt for others further up the stack + interrupted = true; + } + } finally { + if (interrupted) + current.interrupt(); // restore interrupted status + } + } + lockedCount++; + lockHolder = current; + } + + protected synchronized void unlock() { + Thread current = Thread.currentThread(); + if (lockHolder != current) + throw new IllegalStateException("Thread not lock owner"); //$NON-NLS-1$ + + lockedCount--; + if (lockedCount == 0) { + lockHolder = null; + notify(); + } + } + + protected synchronized void checkLocked() { + Thread current = Thread.currentThread(); + if (lockHolder != current) + throw new IllegalStateException("Thread not lock owner"); //$NON-NLS-1$ + } + + protected boolean bind(Bundle bundle) { + try { + lock(); + if (boundBundle == null && (bundleLocation == null || bundleLocation.equals(bundle.getLocation()))) + boundBundle = bundle; + return (boundBundle == bundle); + } finally { + unlock(); + } + } + + protected void unbind(Bundle bundle) { + try { + lock(); + if (boundBundle == bundle) + boundBundle = null; + } finally { + unlock(); + } + } + + public void delete() throws IOException { + try { + lock(); + checkDeleted(); + deleted = true; + configurationAdminFactory.notifyConfigurationDeleted(this, factoryPid != null); + configurationAdminFactory.dispatchEvent(ConfigurationEvent.CM_DELETED, factoryPid, pid); + } finally { + unlock(); + } + configurationStore.removeConfiguration(pid); + } + + private void checkDeleted() { + if (deleted) + throw new IllegalStateException("deleted"); //$NON-NLS-1$ + } + + public String getBundleLocation() { + try { + lock(); + checkDeleted(); + if (bundleLocation != null) + return bundleLocation; + if (boundBundle != null) + return boundBundle.getLocation(); + return null; + } finally { + unlock(); + } + } + + protected String getFactoryPid(boolean checkDeleted) { + try { + lock(); + if (checkDeleted) + checkDeleted(); + return factoryPid; + } finally { + unlock(); + } + } + + public String getFactoryPid() { + return getFactoryPid(true); + } + + protected String getPid(boolean checkDeleted) { + try { + lock(); + if (checkDeleted) + checkDeleted(); + return pid; + } finally { + unlock(); + } + } + + public String getPid() { + return getPid(true); + } + + public Dictionary getProperties() { + try { + lock(); + checkDeleted(); + if (dictionary == null) + return null; + + Dictionary copy = dictionary.copy(); + copy.put(Constants.SERVICE_PID, pid); + if (factoryPid != null) + copy.put(ConfigurationAdmin.SERVICE_FACTORYPID, factoryPid); + + return copy; + } finally { + unlock(); + } + } + + protected Dictionary getAllProperties() { + try { + lock(); + if (deleted) + return null; + Dictionary copy = getProperties(); + if (copy != null && bundleLocation != null) + copy.put(ConfigurationAdmin.SERVICE_BUNDLELOCATION, getBundleLocation()); + return copy; + } finally { + unlock(); + } + } + + public void setBundleLocation(String bundleLocation) { + try { + lock(); + checkDeleted(); + configurationAdminFactory.checkConfigurationPermission(); + this.bundleLocation = bundleLocation; + } finally { + unlock(); + } + } + + public void update() throws IOException { + try { + lock(); + checkDeleted(); + if (dictionary == null) + dictionary = new ConfigurationDictionary(); + configurationStore.saveConfiguration(pid, this); + configurationAdminFactory.notifyConfigurationUpdated(this, factoryPid != null); + } finally { + unlock(); + } + } + + public void update(Dictionary properties) throws IOException { + try { + lock(); + checkDeleted(); + updateDictionary(properties); + configurationStore.saveConfiguration(pid, this); + configurationAdminFactory.notifyConfigurationUpdated(this, factoryPid != null); + configurationAdminFactory.dispatchEvent(ConfigurationEvent.CM_UPDATED, factoryPid, pid); + } finally { + unlock(); + } + } + + private void updateDictionary(Dictionary properties) { + ConfigurationDictionary newDictionary = new ConfigurationDictionary(); + Enumeration keys = properties.keys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + if (newDictionary.get(key) == null) + newDictionary.put(key, properties.get(key)); + else + throw new IllegalArgumentException(key + " is already present or is a case variant."); //$NON-NLS-1$ + } + newDictionary.remove(Constants.SERVICE_PID); + newDictionary.remove(ConfigurationAdmin.SERVICE_FACTORYPID); + newDictionary.remove(ConfigurationAdmin.SERVICE_BUNDLELOCATION); + + dictionary = newDictionary; + } + + public boolean equals(Object obj) { + return pid.equals(((Configuration) obj).getPid()); + } + + public int hashCode() { + return pid.hashCode(); + } + + protected boolean isDeleted() { + try { + lock(); + return deleted; + } finally { + unlock(); + } + } +} \ No newline at end of file Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationStore.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationStore.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ConfigurationStore.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,178 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.io.*; +import java.util.*; +import org.eclipse.equinox.internal.cm.reliablefile.*; +import org.osgi.framework.*; +import org.osgi.service.cm.Configuration; +import org.osgi.service.log.LogService; + +/** + * ConfigurationStore manages all active configurations along with persistence. The current + * implementation uses a filestore and serialization of the configuration dictionaries to files + * identified by their pid. Persistence details are in the constructor, saveConfiguration, and + * deleteConfiguration and can be factored out separately if required. + */ +class ConfigurationStore { + + private final ConfigurationAdminFactory configurationAdminFactory; + private static final String STORE_DIR = "store"; //$NON-NLS-1$ + private static final String PID_EXT = ".pid"; //$NON-NLS-1$ + private final Map configurations = new HashMap(); + private int createdPidCount = 0; + private final File store; + + public ConfigurationStore(ConfigurationAdminFactory configurationAdminFactory, BundleContext context) { + this.configurationAdminFactory = configurationAdminFactory; + store = context.getDataFile(STORE_DIR); + if (store == null) + return; // no persistent store + + store.mkdir(); + File[] configurationFiles = store.listFiles(); + for (int i = 0; i < configurationFiles.length; ++i) { + String configurationFileName = configurationFiles[i].getName(); + if (!configurationFileName.endsWith(PID_EXT)) + continue; + + InputStream ris = null; + ObjectInputStream ois = null; + boolean deleteFile = false; + try { + ris = new ReliableFileInputStream(configurationFiles[i]); + ois = new ObjectInputStream(ris); + Dictionary dictionary = (Dictionary) ois.readObject(); + ConfigurationImpl config = new ConfigurationImpl(configurationAdminFactory, this, dictionary); + configurations.put(config.getPid(), config); + } catch (IOException e) { + String message = e.getMessage(); + String pid = configurationFileName.substring(0, configurationFileName.length() - 4); + String errorMessage = "{Configuration Admin - pid = " + pid + "} could not be restored." + ((message == null) ? "" : " " + message); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + configurationAdminFactory.log(LogService.LOG_ERROR, errorMessage); + deleteFile = true; + } catch (ClassNotFoundException e) { + configurationAdminFactory.log(LogService.LOG_ERROR, e.getMessage()); + } finally { + if (ois != null) { + try { + ois.close(); + } catch (IOException e) { + // ignore + } + } + if (ris != null) { + try { + ris.close(); + } catch (IOException e) { + // ignore + } + } + } + if (deleteFile) { + ReliableFile.delete(configurationFiles[i]); + configurationFiles[i].delete(); + } + } + } + + public void saveConfiguration(String pid, ConfigurationImpl config) throws IOException { + if (store == null) + return; // no persistent store + + config.checkLocked(); + File configFile = new File(store, pid + PID_EXT); + OutputStream ros = null; + ObjectOutputStream oos = null; + try { + configFile.createNewFile(); + ros = new ReliableFileOutputStream(configFile); + oos = new ObjectOutputStream(ros); + oos.writeObject(config.getAllProperties()); + } finally { + if (oos != null) { + try { + oos.close(); + } catch (IOException e) { + // ignore + } + } + if (ros != null) { + try { + ros.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + public synchronized void removeConfiguration(String pid) { + configurations.remove(pid); + if (store == null) + return; // no persistent store + File configFile = new File(store, pid + PID_EXT); + ReliableFile.delete(configFile); + configFile.delete(); + } + + public synchronized Configuration getConfiguration(String pid, String location) { + Configuration config = (Configuration) configurations.get(pid); + if (config == null) { + config = new ConfigurationImpl(configurationAdminFactory, this, null, pid, location); + configurations.put(pid, config); + } + return config; + } + + public synchronized Configuration createFactoryConfiguration(String factoryPid, String location) { + String pid = factoryPid + "-" + new Date().getTime() + "-" + createdPidCount++; //$NON-NLS-1$ //$NON-NLS-2$ + ConfigurationImpl config = new ConfigurationImpl(configurationAdminFactory, this, factoryPid, pid, location); + configurations.put(pid, config); + return config; + } + + public synchronized ConfigurationImpl findConfiguration(String pid) { + return (ConfigurationImpl) configurations.get(pid); + } + + public synchronized ConfigurationImpl[] getFactoryConfigurations(String factoryPid) { + List resultList = new ArrayList(); + for (Iterator it = configurations.values().iterator(); it.hasNext();) { + ConfigurationImpl config = (ConfigurationImpl) it.next(); + String otherFactoryPid = config.getFactoryPid(); + if (otherFactoryPid != null && otherFactoryPid.equals(factoryPid)) + resultList.add(config); + } + return (ConfigurationImpl[]) resultList.toArray(new ConfigurationImpl[0]); + } + + public synchronized Configuration[] listConfigurations(Filter filter) { + List resultList = new ArrayList(); + for (Iterator it = configurations.values().iterator(); it.hasNext();) { + ConfigurationImpl config = (ConfigurationImpl) it.next(); + Dictionary properties = config.getAllProperties(); + if (properties != null && filter.match(properties)) + resultList.add(config); + } + int size = resultList.size(); + return size == 0 ? null : (Configuration[]) resultList.toArray(new Configuration[size]); + } + + public synchronized void unbindConfigurations(Bundle bundle) { + for (Iterator it = configurations.values().iterator(); it.hasNext();) { + ConfigurationImpl config = (ConfigurationImpl) it.next(); + config.unbind(bundle); + } + } +} \ No newline at end of file Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/EventDispatcher.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/EventDispatcher.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/EventDispatcher.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.cm.ConfigurationEvent; +import org.osgi.service.cm.ConfigurationListener; +import org.osgi.service.log.LogService; +import org.osgi.util.tracker.ServiceTracker; + +/** + * EventDispatcher is responsible for delivering Configuration Events to ConfigurationListeners. + * The originating ConfigAdmin ServiceReference is needed when delivering events. This reference + * is made available by the service factory before returning the service object. + */ + +public class EventDispatcher { + final ServiceTracker tracker; + private final SerializedTaskQueue queue = new SerializedTaskQueue("ConfigurationListener Event Queue"); //$NON-NLS-1$ + /** @GuardedBy this */ + private ServiceReference configAdminReference; + final LogService log; + + public EventDispatcher(BundleContext context, LogService log) { + this.log = log; + tracker = new ServiceTracker(context, ConfigurationListener.class.getName(), null); + } + + public void start() { + tracker.open(); + } + + public void stop() { + tracker.close(); + synchronized (this) { + configAdminReference = null; + } + } + + synchronized void setServiceReference(ServiceReference reference) { + if (configAdminReference == null) + configAdminReference = reference; + } + + public void dispatchEvent(int type, String factoryPid, String pid) { + final ConfigurationEvent event = createConfigurationEvent(type, factoryPid, pid); + if (event == null) + return; + + ServiceReference[] refs = tracker.getServiceReferences(); + if (refs == null) + return; + + for (int i = 0; i < refs.length; ++i) { + final ServiceReference ref = refs[i]; + queue.put(new Runnable() { + public void run() { + ConfigurationListener listener = (ConfigurationListener) tracker.getService(ref); + if (listener == null) { + return; + } + try { + listener.configurationEvent(event); + } catch (Throwable t) { + log.log(LogService.LOG_ERROR, t.getMessage(), t); + } + } + }); + } + } + + private synchronized ConfigurationEvent createConfigurationEvent(int type, String factoryPid, String pid) { + if (configAdminReference == null) + return null; + + return new ConfigurationEvent(configAdminReference, type, factoryPid, pid); + } +} Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/LogTracker.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/LogTracker.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/LogTracker.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 1998, 2007 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.io.PrintStream; +import java.util.Calendar; +import java.util.Date; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.log.LogService; +import org.osgi.util.tracker.ServiceTracker; + +/** + * LogTracker class. This class encapsulates the LogService + * and handles all issues such as the service coming and going. + */ + +public class LogTracker extends ServiceTracker implements LogService { + /** LogService interface class name */ + protected final static String clazz = "org.osgi.service.log.LogService"; //$NON-NLS-1$ + + /** PrintStream to use if LogService is unavailable */ + private final PrintStream out; + + /** + * Create new LogTracker. + * + * @param context BundleContext of parent bundle. + * @param out Default PrintStream to use if LogService is unavailable. + */ + public LogTracker(BundleContext context, PrintStream out) { + super(context, clazz, null); + this.out = out; + } + + /* + * ---------------------------------------------------------------------- + * LogService Interface implementation + * ---------------------------------------------------------------------- + */ + + public void log(int level, String message) { + log(null, level, message, null); + } + + public void log(int level, String message, Throwable exception) { + log(null, level, message, exception); + } + + public void log(ServiceReference reference, int level, String message) { + log(reference, level, message, null); + } + + public synchronized void log(ServiceReference reference, int level, String message, Throwable exception) { + ServiceReference[] references = getServiceReferences(); + + if (references != null) { + int size = references.length; + + for (int i = 0; i < size; i++) { + LogService service = (LogService) getService(references[i]); + if (service != null) { + try { + service.log(reference, level, message, exception); + } catch (Exception e) { + // TODO: consider printing to System Error + } + } + } + + return; + } + + noLogService(level, message, exception, reference); + } + + /** + * The LogService is not available so we write the message to a PrintStream. + * + * @param level Logging level + * @param message Log message. + * @param throwable Log exception or null if none. + * @param reference ServiceReference associated with message or null if none. + */ + protected void noLogService(int level, String message, Throwable throwable, ServiceReference reference) { + if (out != null) { + synchronized (out) { + // Bug #113286. If no log service present and messages are being + // printed to stdout, prepend message with a timestamp. + String timestamp = getDate(new Date()); + out.print(timestamp + " "); //$NON-NLS-1$ + + switch (level) { + case LOG_DEBUG : { + out.print("Debug"); //$NON-NLS-1$ + break; + } + case LOG_INFO : { + out.print("Info"); //$NON-NLS-1$ + break; + } + case LOG_WARNING : { + out.print("Warning"); //$NON-NLS-1$ + break; + } + case LOG_ERROR : { + out.print("Error"); //$NON-NLS-1$ + break; + } + default : { + out.print("["); //$NON-NLS-1$ + out.print("Unknown Log Level"); //$NON-NLS-1$ + out.print("]"); //$NON-NLS-1$ + break; + } + } + out.print(": "); //$NON-NLS-1$ + out.println(message); + + if (reference != null) { + out.println(reference); + } + + if (throwable != null) { + throwable.printStackTrace(out); + } + } + } + } + + // from EclipseLog to avoid using DateFormat -- see bug 149892#c10 + private String getDate(Date date) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + StringBuffer sb = new StringBuffer(); + appendPaddedInt(c.get(Calendar.YEAR), 4, sb).append('-'); + appendPaddedInt(c.get(Calendar.MONTH) + 1, 2, sb).append('-'); + appendPaddedInt(c.get(Calendar.DAY_OF_MONTH), 2, sb).append(' '); + appendPaddedInt(c.get(Calendar.HOUR_OF_DAY), 2, sb).append(':'); + appendPaddedInt(c.get(Calendar.MINUTE), 2, sb).append(':'); + appendPaddedInt(c.get(Calendar.SECOND), 2, sb).append('.'); + appendPaddedInt(c.get(Calendar.MILLISECOND), 3, sb); + return sb.toString(); + } + + private StringBuffer appendPaddedInt(int value, int pad, StringBuffer buffer) { + pad = pad - 1; + if (pad == 0) + return buffer.append(Integer.toString(value)); + int padding = (int) Math.pow(10, pad); + if (value >= padding) + return buffer.append(Integer.toString(value)); + while (padding > value && padding > 1) { + buffer.append('0'); + padding = padding / 10; + } + buffer.append(value); + return buffer; + } +} Added: branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java =================================================================== --- branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java (rev 0) +++ branches/user_prefs/org.eclipse.equinox.cm/src/org/eclipse/equinox/internal/cm/ManagedServiceFactoryTracker.java 2008-03-21 17:39:47 UTC (rev 676) @@ -0,0 +1,188 @@ +/******************************************************************************* + * Copyright (c) 2006-2007 Cognos Incorporated, IBM Corporation 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: + * Cognos Incorporated - initial API and implementation + * IBM Corporation - bug fixes and enhancements + *******************************************************************************/ +package org.eclipse.equinox.internal.cm; + +import java.util.*; +import java.util.Map.Entry; +import org.osgi.framework.*; +import org.osgi.service.cm.ConfigurationException; +import org.osgi.service.cm.ManagedServiceFactory; +import org.osgi.service.log.LogService; +import org.osgi.util.tracker.ServiceTracker; + +/** + * ManagedServiceFactoryTracker tracks... ManagedServiceFactory(s) and notifies them about related configuration changes + */ +class ManagedServiceFactoryTracker extends ServiceTracker { + + final ConfigurationAdminFactory configurationAdminFactory; + private final ConfigurationStore configurationStore; + private final Map managedServiceFactories = new HashMap(); + private final Map managedServiceFactoryReferences = new HashMap(); + private final SerializedTaskQueue queue = new SerializedTaskQueue("ManagedServiceFactory Update Queue"); //$NON-NLS-1$ + + public ManagedServiceFactoryTracker(ConfigurationAdminFactory configurationAdminFactory, ConfigurationStore configurationStore, BundleContext context) { + super(context, ManagedServiceFactory.class.getName(), null); + this.configurationAdminFactory = configurationAdminFactory; + this.configurationStore = configurationStore; + } + + protected void notifyDeleted(ConfigurationImpl config) { + config.checkLocked(); + String factoryPid = config.getFactoryPid(false); + ServiceReference reference = getManagedServiceFactoryReference(factoryPid); + if (reference != null && config.bind(reference.getBundle())) + asynchDeleted(getManagedServiceFactory(factoryPid), config.getPid(false)); + } + + protected void notifyUpdated(ConfigurationImpl config) { + config.checkLocked(); + String factoryPid = config.getFactoryPid(); + ServiceReference reference = getManagedServiceFactoryReference(factoryPid); + if (reference != null && config.bind(reference.getBundle())) { + Dictionary properties = config.getProperties(); + configurationAdminFactory.modifyConfiguration(reference, properties); + asynchUpdated(getManagedServiceFactory(factoryPid), config.getPid(), properties); + } + } + + public Object addingService(ServiceReference reference) { + String factoryPid = (String) reference.getProperty(Constants.SERVICE_PID); + if (factoryPid == null) + return null; + + ManagedServiceFactory service = (... [truncated message content] |