From 0609664b9dfe07dea5c53a06106a9abf9a4d638a Mon Sep 17 00:00:00 2001 From: BJ Hargrave Date: Wed, 28 Sep 2011 15:39:24 -0400 Subject: Convert line endings to LF --- .../metatype/EquinoxAttributeDefinition.java | 38 +- .../metatype/EquinoxMetaTypeInformation.java | 38 +- .../equinox/metatype/EquinoxMetaTypeService.java | 40 +- .../metatype/EquinoxObjectClassDefinition.java | 38 +- .../org/eclipse/equinox/metatype/Extendable.java | 44 +- .../eclipse/equinox/metatype/impl/Activator.java | 510 ++-- .../metatype/impl/AttributeDefinitionImpl.java | 622 ++--- .../eclipse/equinox/metatype/impl/DataParser.java | 1698 +++++++------- .../eclipse/equinox/metatype/impl/Designate.java | 208 +- .../equinox/metatype/impl/ExtendableHelper.java | 78 +- .../metatype/impl/ExternalMessages.properties | 72 +- .../equinox/metatype/impl/FragmentUtils.java | 116 +- .../org/eclipse/equinox/metatype/impl/Icon.java | 144 +- .../equinox/metatype/impl/LocalizationElement.java | 110 +- .../equinox/metatype/impl/LogMessages.properties | 34 +- .../eclipse/equinox/metatype/impl/LogTracker.java | 354 +-- .../equinox/metatype/impl/LogTrackerMsg.java | 56 +- .../metatype/impl/MetaTypeInformationImpl.java | 178 +- .../eclipse/equinox/metatype/impl/MetaTypeMsg.java | 90 +- .../metatype/impl/MetaTypeProviderImpl.java | 478 ++-- .../metatype/impl/MetaTypeProviderTracker.java | 574 ++--- .../equinox/metatype/impl/MetaTypeServiceImpl.java | 274 +-- .../metatype/impl/ObjectClassDefinitionImpl.java | 640 ++--- .../equinox/metatype/impl/ValueTokenizer.java | 548 ++--- .../internal/preferences/EclipsePreferences.java | 2476 ++++++++++---------- .../osgi/service/prefs/BackingStoreException.java | 2 +- .../src/org/osgi/service/prefs/Preferences.java | 2 +- .../org/osgi/service/prefs/PreferencesService.java | 2 +- .../src/org/osgi/service/resolver/Resolver.java | 2 +- .../org/osgi/service/resolver/package-info.java | 2 +- 30 files changed, 4734 insertions(+), 4734 deletions(-) diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxAttributeDefinition.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxAttributeDefinition.java index fb0e85c3c..5baaae0b7 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxAttributeDefinition.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxAttributeDefinition.java @@ -1,19 +1,19 @@ -/******************************************************************************* - * Copyright (c) 2011 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 - ******************************************************************************/ -package org.eclipse.equinox.metatype; - -import org.osgi.service.metatype.AttributeDefinition; - -/** - * - * @since 1.2 - * - */ -public interface EquinoxAttributeDefinition extends AttributeDefinition, Extendable { - // Empty interface to support extendable attribute definitions. -} +/******************************************************************************* + * Copyright (c) 2011 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 + ******************************************************************************/ +package org.eclipse.equinox.metatype; + +import org.osgi.service.metatype.AttributeDefinition; + +/** + * + * @since 1.2 + * + */ +public interface EquinoxAttributeDefinition extends AttributeDefinition, Extendable { + // Empty interface to support extendable attribute definitions. +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeInformation.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeInformation.java index 70b79a76f..345d79d55 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeInformation.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeInformation.java @@ -1,19 +1,19 @@ -/******************************************************************************* - * Copyright (c) 2011 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 - ******************************************************************************/ -package org.eclipse.equinox.metatype; - -import org.osgi.service.metatype.MetaTypeInformation; - -/** - * - * @since 1.2 - * - */ -public interface EquinoxMetaTypeInformation extends MetaTypeInformation { - EquinoxObjectClassDefinition getObjectClassDefinition(String id, String locale); -} +/******************************************************************************* + * Copyright (c) 2011 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 + ******************************************************************************/ +package org.eclipse.equinox.metatype; + +import org.osgi.service.metatype.MetaTypeInformation; + +/** + * + * @since 1.2 + * + */ +public interface EquinoxMetaTypeInformation extends MetaTypeInformation { + EquinoxObjectClassDefinition getObjectClassDefinition(String id, String locale); +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeService.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeService.java index a9ba9c0c2..e2154f5bf 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeService.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxMetaTypeService.java @@ -1,20 +1,20 @@ -/******************************************************************************* - * Copyright (c) 2011 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 - ******************************************************************************/ -package org.eclipse.equinox.metatype; - -import org.osgi.framework.Bundle; -import org.osgi.service.metatype.MetaTypeService; - -/** - * - * @since 1.2 - * - */ -public interface EquinoxMetaTypeService extends MetaTypeService { - EquinoxMetaTypeInformation getMetaTypeInformation(Bundle bundle); -} +/******************************************************************************* + * Copyright (c) 2011 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 + ******************************************************************************/ +package org.eclipse.equinox.metatype; + +import org.osgi.framework.Bundle; +import org.osgi.service.metatype.MetaTypeService; + +/** + * + * @since 1.2 + * + */ +public interface EquinoxMetaTypeService extends MetaTypeService { + EquinoxMetaTypeInformation getMetaTypeInformation(Bundle bundle); +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxObjectClassDefinition.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxObjectClassDefinition.java index f8d0e8039..efb8c3ff3 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxObjectClassDefinition.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/EquinoxObjectClassDefinition.java @@ -1,19 +1,19 @@ -/******************************************************************************* - * Copyright (c) 2011 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 - ******************************************************************************/ -package org.eclipse.equinox.metatype; - -import org.osgi.service.metatype.ObjectClassDefinition; - -/** - * - * @since 1.2 - * - */ -public interface EquinoxObjectClassDefinition extends ObjectClassDefinition, Extendable { - EquinoxAttributeDefinition[] getAttributeDefinitions(int filter); -} +/******************************************************************************* + * Copyright (c) 2011 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 + ******************************************************************************/ +package org.eclipse.equinox.metatype; + +import org.osgi.service.metatype.ObjectClassDefinition; + +/** + * + * @since 1.2 + * + */ +public interface EquinoxObjectClassDefinition extends ObjectClassDefinition, Extendable { + EquinoxAttributeDefinition[] getAttributeDefinitions(int filter); +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/Extendable.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/Extendable.java index 7d52b498b..4f6069ec5 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/Extendable.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/Extendable.java @@ -1,22 +1,22 @@ -/******************************************************************************* - * Copyright (c) 2011 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 - ******************************************************************************/ -package org.eclipse.equinox.metatype; - -import java.util.Map; -import java.util.Set; - -/** - * - * @since 1.2 - * - */ -public interface Extendable { - Map getExtensionAttributes(String uri); - - Set getExtensionUris(); -} +/******************************************************************************* + * Copyright (c) 2011 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 + ******************************************************************************/ +package org.eclipse.equinox.metatype; + +import java.util.Map; +import java.util.Set; + +/** + * + * @since 1.2 + * + */ +public interface Extendable { + Map getExtensionAttributes(String uri); + + Set getExtensionUris(); +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Activator.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Activator.java index 014a36cd5..3daf3f4f3 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Activator.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Activator.java @@ -1,255 +1,255 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.EquinoxMetaTypeService; - -import java.util.Dictionary; -import java.util.Hashtable; -import javax.xml.parsers.SAXParserFactory; -import org.osgi.framework.*; -import org.osgi.service.cm.ManagedService; -import org.osgi.service.log.LogService; -import org.osgi.service.metatype.MetaTypeProvider; -import org.osgi.service.metatype.MetaTypeService; -import org.osgi.util.tracker.ServiceTracker; -import org.osgi.util.tracker.ServiceTrackerCustomizer; - -/** - * MetaType Activator - */ -public class Activator implements BundleActivator { - /* - * The following filter guarantees only services meeting the following - * criteria will be tracked. - * - * (1) A ManagedService or ManagedServiceFactory registered with a - * SERVICE_PID property. May also be registered as a MetaTypeProvider. - * (2) A MetaTypeProvider registered with a METATYPE_PID or - * METATYPE_FACTORY_PID property. - * - * Note that it's still necessary to inspect a ManagedService or - * ManagedServiceFactory to ensure it also implements MetaTypeProvider. - */ - private static final String FILTER = "(|(&(" + Constants.OBJECTCLASS + '=' + ManagedService.class.getName() + "*)(" + Constants.SERVICE_PID + "=*))(&(" + Constants.OBJECTCLASS + '=' + MetaTypeProvider.class.getName() + ")(|(" + MetaTypeProvider.METATYPE_PID + "=*)(" + MetaTypeProvider.METATYPE_FACTORY_PID + "=*))))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ - private static final String SERVICE_PID = "org.osgi.impl.service.metatype.MetaTypeService"; //$NON-NLS-1$ - - private LogTracker logServiceTracker; - // Could be ManagedService, ManagedServiceFactory, or MetaTypeProvider. - // The tracker tracks all services regardless of bundle. Services are - // filtered by bundle later in the MetaTypeProviderTracker class. It may - // therefore be shared among multiple instances of that class. - private ServiceTracker metaTypeProviderTracker; - private ServiceTracker saxParserFactoryTracker; - - public void start(BundleContext context) throws InvalidSyntaxException { - LogTracker lsTracker; - ServiceTracker mtpTracker; - ServiceTracker spfTracker; - Filter filter = context.createFilter(FILTER); - synchronized (this) { - lsTracker = logServiceTracker = new LogTracker(context, System.out); - mtpTracker = metaTypeProviderTracker = new ServiceTracker(context, filter, null); - spfTracker = saxParserFactoryTracker = new ServiceTracker(context, SAXParserFactory.class, new SAXParserFactoryTrackerCustomizer(context, lsTracker, mtpTracker)); - } - // Do this first to make logging available as early as possible. - lsTracker.open(); - lsTracker.log(LogService.LOG_DEBUG, "====== Meta Type Service starting ! ====="); //$NON-NLS-1$ - // Do this next to make MetaTypeProviders available as early as possible. - mtpTracker.open(); - // Do this last because it may result in the MetaTypeService being registered. - spfTracker.open(); - } - - public void stop(BundleContext context) { - ServiceTracker spfTracker; - ServiceTracker mtpTracker; - LogTracker lsTracker; - synchronized (this) { - spfTracker = saxParserFactoryTracker; - // Set this to null so the SAXParserFactoryTrackerCustomizer knows - // not to register a new MetaTypeService when removedService() is - // called while the tracker is closing. - saxParserFactoryTracker = null; - mtpTracker = metaTypeProviderTracker; - lsTracker = logServiceTracker; - } - lsTracker.log(LogService.LOG_DEBUG, "====== Meta Type Service stopping ! ====="); //$NON-NLS-1$ - spfTracker.close(); - mtpTracker.close(); - // Do this last to leave logging available as long as possible. - lsTracker.close(); - } - - synchronized ServiceTracker getSAXParserFactoryTracker() { - return saxParserFactoryTracker; - } - - private class SAXParserFactoryTrackerCustomizer implements ServiceTrackerCustomizer { - private final BundleContext bundleCtx; - private final LogService logService; - private final ServiceTracker mtpTracker; - - private MetaTypeServiceImpl metaTypeService; - private ServiceRegistration metaTypeServiceRegistration; - private SAXParserFactory saxParserFactory; - - public SAXParserFactoryTrackerCustomizer(BundleContext bundleContext, LogService logService, ServiceTracker metaTypeProviderTracker) { - this.bundleCtx = bundleContext; - this.logService = logService; - this.mtpTracker = metaTypeProviderTracker; - } - - public SAXParserFactory addingService(ServiceReference ref) { - SAXParserFactory parserFactory = bundleCtx.getService(ref); - if (parserFactory == null) - return null; - ServiceRegistration registration = null; - MetaTypeServiceImpl service = null; - SAXParserFactory oldFactory = null; - synchronized (this) { - // No previous factory case. We'll accept anything. - if (saxParserFactory == null) { - // Save this parserFactory as the currently used parserFactory - saxParserFactory = parserFactory; - } - // Nothing to do case. Current factory is explicitly namespace aware. - else if (saxParserFactory.isNamespaceAware()) { - return parserFactory; - } else if (parserFactory.isNamespaceAware() || // Previous factory not set for namespace awareness but the new one is case. - // Now the fun case. Neither factory is set for namespace awareness. Need to see if we're currently using - // a factory incapable of creating namespace aware parsers and, if so, if it can be replaced with the new one. - (!supportsNamespaceAwareness(saxParserFactory) && supportsNamespaceAwareness(parserFactory))) { - oldFactory = saxParserFactory; - saxParserFactory = parserFactory; - registration = metaTypeServiceRegistration; - service = metaTypeService; - } - } - swapFactories(oldFactory, parserFactory, registration, service); - return parserFactory; - } - - private void swapFactories(SAXParserFactory oldFactory, SAXParserFactory newFactory, ServiceRegistration registration, MetaTypeServiceImpl service) { - if (oldFactory == null) { - registerMetaTypeService(); - return; - } - unregisterMetaTypeService(registration, service); - registerMetaTypeService(); - } - - public void modifiedService(ServiceReference ref, SAXParserFactory object) { - // Nothing. - } - - public void removedService(ServiceReference ref, SAXParserFactory object) { - ServiceRegistration registration = null; - MetaTypeServiceImpl service = null; - synchronized (this) { - if (object == saxParserFactory) { - // This means the SAXParserFactory was used to start the MetaTypeService and we need to reset. - saxParserFactory = null; - registration = metaTypeServiceRegistration; - service = metaTypeService; - } - } - if (registration != null) { - // Unregister the MetaType service. - unregisterMetaTypeService(registration, service); - // See if another factory is available - SAXParserFactory factory = findBestPossibleFactory(); - // If the factory is null, either the bundle is stopping or there are no - // available services. Either way, we don't want to register the MetaType service. - if (factory != null) { - // We have another parser so let's restart the MetaType service if it hasn't been already. - boolean register = false; - synchronized (this) { - // If not null, something else beat us to the punch. - if (saxParserFactory == null) { - saxParserFactory = factory; - register = true; - } - } - if (register) { - registerMetaTypeService(); - } - } - } - bundleCtx.ungetService(ref); - } - - private SAXParserFactory findBestPossibleFactory() { - ServiceTracker tracker = getSAXParserFactoryTracker(); - // The tracker will be null if the bundle is stopping. - if (tracker == null) - return null; - SAXParserFactory[] factories = (SAXParserFactory[]) tracker.getServices(); - // The factories will be null if there are no services being tracked. - if (factories == null) - return null; - SAXParserFactory result = null; - for (SAXParserFactory factory : factories) { - if (factory.isNamespaceAware()) { - // If the factory is namespace aware, we have exactly what we want. - result = factory; - break; - } - // If no "second best" parser has been found yet, see if this one fits the bill. - if (result == null && supportsNamespaceAwareness(factory)) { - result = factory; - } - } - // If no factories capable of providing namespace aware parsers have been found, - // just grab the first available one, if any. - if (result == null) - result = tracker.getService(); - return result; - } - - private void registerMetaTypeService() { - Dictionary properties = new Hashtable(7); - properties = new Hashtable(7); - properties.put(Constants.SERVICE_VENDOR, "IBM"); //$NON-NLS-1$ - properties.put(Constants.SERVICE_DESCRIPTION, MetaTypeMsg.SERVICE_DESCRIPTION); - properties.put(Constants.SERVICE_PID, SERVICE_PID); - MetaTypeServiceImpl service; - synchronized (this) { - service = metaTypeService = new MetaTypeServiceImpl(saxParserFactory, logService, mtpTracker); - } - bundleCtx.addBundleListener(service); - ServiceRegistration registration = bundleCtx.registerService(new String[] {MetaTypeService.class.getName(), EquinoxMetaTypeService.class.getName()}, service, properties); - synchronized (this) { - metaTypeServiceRegistration = registration; - } - } - - private boolean supportsNamespaceAwareness(SAXParserFactory factory) { - if (factory.isNamespaceAware()) - return true; - factory.setNamespaceAware(true); - try { - factory.newSAXParser(); - return true; - } catch (Exception e) { - return false; - } finally { - // Go back to the original settings. - factory.setNamespaceAware(false); - } - } - - private void unregisterMetaTypeService(ServiceRegistration registration, MetaTypeServiceImpl service) { - registration.unregister(); - bundleCtx.removeBundleListener(service); - } - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.EquinoxMetaTypeService; + +import java.util.Dictionary; +import java.util.Hashtable; +import javax.xml.parsers.SAXParserFactory; +import org.osgi.framework.*; +import org.osgi.service.cm.ManagedService; +import org.osgi.service.log.LogService; +import org.osgi.service.metatype.MetaTypeProvider; +import org.osgi.service.metatype.MetaTypeService; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +/** + * MetaType Activator + */ +public class Activator implements BundleActivator { + /* + * The following filter guarantees only services meeting the following + * criteria will be tracked. + * + * (1) A ManagedService or ManagedServiceFactory registered with a + * SERVICE_PID property. May also be registered as a MetaTypeProvider. + * (2) A MetaTypeProvider registered with a METATYPE_PID or + * METATYPE_FACTORY_PID property. + * + * Note that it's still necessary to inspect a ManagedService or + * ManagedServiceFactory to ensure it also implements MetaTypeProvider. + */ + private static final String FILTER = "(|(&(" + Constants.OBJECTCLASS + '=' + ManagedService.class.getName() + "*)(" + Constants.SERVICE_PID + "=*))(&(" + Constants.OBJECTCLASS + '=' + MetaTypeProvider.class.getName() + ")(|(" + MetaTypeProvider.METATYPE_PID + "=*)(" + MetaTypeProvider.METATYPE_FACTORY_PID + "=*))))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + private static final String SERVICE_PID = "org.osgi.impl.service.metatype.MetaTypeService"; //$NON-NLS-1$ + + private LogTracker logServiceTracker; + // Could be ManagedService, ManagedServiceFactory, or MetaTypeProvider. + // The tracker tracks all services regardless of bundle. Services are + // filtered by bundle later in the MetaTypeProviderTracker class. It may + // therefore be shared among multiple instances of that class. + private ServiceTracker metaTypeProviderTracker; + private ServiceTracker saxParserFactoryTracker; + + public void start(BundleContext context) throws InvalidSyntaxException { + LogTracker lsTracker; + ServiceTracker mtpTracker; + ServiceTracker spfTracker; + Filter filter = context.createFilter(FILTER); + synchronized (this) { + lsTracker = logServiceTracker = new LogTracker(context, System.out); + mtpTracker = metaTypeProviderTracker = new ServiceTracker(context, filter, null); + spfTracker = saxParserFactoryTracker = new ServiceTracker(context, SAXParserFactory.class, new SAXParserFactoryTrackerCustomizer(context, lsTracker, mtpTracker)); + } + // Do this first to make logging available as early as possible. + lsTracker.open(); + lsTracker.log(LogService.LOG_DEBUG, "====== Meta Type Service starting ! ====="); //$NON-NLS-1$ + // Do this next to make MetaTypeProviders available as early as possible. + mtpTracker.open(); + // Do this last because it may result in the MetaTypeService being registered. + spfTracker.open(); + } + + public void stop(BundleContext context) { + ServiceTracker spfTracker; + ServiceTracker mtpTracker; + LogTracker lsTracker; + synchronized (this) { + spfTracker = saxParserFactoryTracker; + // Set this to null so the SAXParserFactoryTrackerCustomizer knows + // not to register a new MetaTypeService when removedService() is + // called while the tracker is closing. + saxParserFactoryTracker = null; + mtpTracker = metaTypeProviderTracker; + lsTracker = logServiceTracker; + } + lsTracker.log(LogService.LOG_DEBUG, "====== Meta Type Service stopping ! ====="); //$NON-NLS-1$ + spfTracker.close(); + mtpTracker.close(); + // Do this last to leave logging available as long as possible. + lsTracker.close(); + } + + synchronized ServiceTracker getSAXParserFactoryTracker() { + return saxParserFactoryTracker; + } + + private class SAXParserFactoryTrackerCustomizer implements ServiceTrackerCustomizer { + private final BundleContext bundleCtx; + private final LogService logService; + private final ServiceTracker mtpTracker; + + private MetaTypeServiceImpl metaTypeService; + private ServiceRegistration metaTypeServiceRegistration; + private SAXParserFactory saxParserFactory; + + public SAXParserFactoryTrackerCustomizer(BundleContext bundleContext, LogService logService, ServiceTracker metaTypeProviderTracker) { + this.bundleCtx = bundleContext; + this.logService = logService; + this.mtpTracker = metaTypeProviderTracker; + } + + public SAXParserFactory addingService(ServiceReference ref) { + SAXParserFactory parserFactory = bundleCtx.getService(ref); + if (parserFactory == null) + return null; + ServiceRegistration registration = null; + MetaTypeServiceImpl service = null; + SAXParserFactory oldFactory = null; + synchronized (this) { + // No previous factory case. We'll accept anything. + if (saxParserFactory == null) { + // Save this parserFactory as the currently used parserFactory + saxParserFactory = parserFactory; + } + // Nothing to do case. Current factory is explicitly namespace aware. + else if (saxParserFactory.isNamespaceAware()) { + return parserFactory; + } else if (parserFactory.isNamespaceAware() || // Previous factory not set for namespace awareness but the new one is case. + // Now the fun case. Neither factory is set for namespace awareness. Need to see if we're currently using + // a factory incapable of creating namespace aware parsers and, if so, if it can be replaced with the new one. + (!supportsNamespaceAwareness(saxParserFactory) && supportsNamespaceAwareness(parserFactory))) { + oldFactory = saxParserFactory; + saxParserFactory = parserFactory; + registration = metaTypeServiceRegistration; + service = metaTypeService; + } + } + swapFactories(oldFactory, parserFactory, registration, service); + return parserFactory; + } + + private void swapFactories(SAXParserFactory oldFactory, SAXParserFactory newFactory, ServiceRegistration registration, MetaTypeServiceImpl service) { + if (oldFactory == null) { + registerMetaTypeService(); + return; + } + unregisterMetaTypeService(registration, service); + registerMetaTypeService(); + } + + public void modifiedService(ServiceReference ref, SAXParserFactory object) { + // Nothing. + } + + public void removedService(ServiceReference ref, SAXParserFactory object) { + ServiceRegistration registration = null; + MetaTypeServiceImpl service = null; + synchronized (this) { + if (object == saxParserFactory) { + // This means the SAXParserFactory was used to start the MetaTypeService and we need to reset. + saxParserFactory = null; + registration = metaTypeServiceRegistration; + service = metaTypeService; + } + } + if (registration != null) { + // Unregister the MetaType service. + unregisterMetaTypeService(registration, service); + // See if another factory is available + SAXParserFactory factory = findBestPossibleFactory(); + // If the factory is null, either the bundle is stopping or there are no + // available services. Either way, we don't want to register the MetaType service. + if (factory != null) { + // We have another parser so let's restart the MetaType service if it hasn't been already. + boolean register = false; + synchronized (this) { + // If not null, something else beat us to the punch. + if (saxParserFactory == null) { + saxParserFactory = factory; + register = true; + } + } + if (register) { + registerMetaTypeService(); + } + } + } + bundleCtx.ungetService(ref); + } + + private SAXParserFactory findBestPossibleFactory() { + ServiceTracker tracker = getSAXParserFactoryTracker(); + // The tracker will be null if the bundle is stopping. + if (tracker == null) + return null; + SAXParserFactory[] factories = (SAXParserFactory[]) tracker.getServices(); + // The factories will be null if there are no services being tracked. + if (factories == null) + return null; + SAXParserFactory result = null; + for (SAXParserFactory factory : factories) { + if (factory.isNamespaceAware()) { + // If the factory is namespace aware, we have exactly what we want. + result = factory; + break; + } + // If no "second best" parser has been found yet, see if this one fits the bill. + if (result == null && supportsNamespaceAwareness(factory)) { + result = factory; + } + } + // If no factories capable of providing namespace aware parsers have been found, + // just grab the first available one, if any. + if (result == null) + result = tracker.getService(); + return result; + } + + private void registerMetaTypeService() { + Dictionary properties = new Hashtable(7); + properties = new Hashtable(7); + properties.put(Constants.SERVICE_VENDOR, "IBM"); //$NON-NLS-1$ + properties.put(Constants.SERVICE_DESCRIPTION, MetaTypeMsg.SERVICE_DESCRIPTION); + properties.put(Constants.SERVICE_PID, SERVICE_PID); + MetaTypeServiceImpl service; + synchronized (this) { + service = metaTypeService = new MetaTypeServiceImpl(saxParserFactory, logService, mtpTracker); + } + bundleCtx.addBundleListener(service); + ServiceRegistration registration = bundleCtx.registerService(new String[] {MetaTypeService.class.getName(), EquinoxMetaTypeService.class.getName()}, service, properties); + synchronized (this) { + metaTypeServiceRegistration = registration; + } + } + + private boolean supportsNamespaceAwareness(SAXParserFactory factory) { + if (factory.isNamespaceAware()) + return true; + factory.setNamespaceAware(true); + try { + factory.newSAXParser(); + return true; + } catch (Exception e) { + return false; + } finally { + // Go back to the original settings. + factory.setNamespaceAware(false); + } + } + + private void unregisterMetaTypeService(ServiceRegistration registration, MetaTypeServiceImpl service) { + registration.unregister(); + bundleCtx.removeBundleListener(service); + } + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/AttributeDefinitionImpl.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/AttributeDefinitionImpl.java index 6b4d3b583..73d34da39 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/AttributeDefinitionImpl.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/AttributeDefinitionImpl.java @@ -1,311 +1,311 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.EquinoxAttributeDefinition; - -import java.util.*; -import org.eclipse.osgi.util.NLS; -import org.osgi.service.log.LogService; - -/** - * Implementation of AttributeDefintion - */ -public class AttributeDefinitionImpl extends LocalizationElement implements EquinoxAttributeDefinition, Cloneable { - - String _name; - String _id; - String _description; - int _cardinality = 0; - int _dataType; - Object _minValue = null; - Object _maxValue = null; - boolean _isRequired = true; - - String[] _defaults = null; - Vector _values = new Vector(7); - Vector _labels = new Vector(7); - - private final LogService logger; - private final ExtendableHelper helper; - - /** - * Constructor of class AttributeDefinitionImpl. - */ - public AttributeDefinitionImpl(String id, String name, String description, int type, int cardinality, Object min, Object max, boolean isRequired, String localization, LogService logger, Map> extensionAttributes) { - this(id, name, description, type, cardinality, min, max, isRequired, localization, logger, new ExtendableHelper(extensionAttributes)); - } - - private AttributeDefinitionImpl(String id, String name, String description, int type, int cardinality, Object min, Object max, boolean isRequired, String localization, LogService logger, ExtendableHelper helper) { - this._id = id; - this._name = name; - this._description = description; - this._dataType = type; - this._cardinality = cardinality; - this._minValue = min; - this._maxValue = max; - this._isRequired = isRequired; - this._localization = localization; - this.logger = logger; - this.helper = helper; - } - - /* - * - */ - public synchronized Object clone() { - - AttributeDefinitionImpl ad = new AttributeDefinitionImpl(_id, _name, _description, _dataType, _cardinality, _minValue, _maxValue, _isRequired, _localization, logger, helper); - - if (_defaults != null) { - ad.setDefaultValue(_defaults.clone()); - } - if ((_labels != null) && (_values != null)) { - @SuppressWarnings("unchecked") - Vector labels = (Vector) _labels.clone(); - @SuppressWarnings("unchecked") - Vector values = (Vector) _values.clone(); - ad.setOption(labels, values, false); - } - - return ad; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getName() - */ - public String getName() { - return getLocalized(_name); - } - - /** - * Method to set the name of AttributeDefinition. - */ - void setName(String name) { - this._name = name; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getID() - */ - public String getID() { - return _id; - } - - /** - * Method to set the ID of AttributeDefinition. - */ - void setID(String id) { - this._id = id; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getDescription() - */ - public String getDescription() { - return getLocalized(_description); - } - - /** - * Method to set the description of AttributeDefinition. - */ - void setDescription(String description) { - this._description = description; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getCardinality() - */ - public int getCardinality() { - return _cardinality; - } - - /** - * Method to set the cardinality of AttributeDefinition. - */ - void setCardinality(int cardinality) { - this._cardinality = cardinality; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getType() - */ - public int getType() { - return _dataType; - } - - /** - * Method to set the data type of AttributeDefinition. - */ - void setType(int type) { - this._dataType = type; - } - - /** - * Method to get the required flag of AttributeDefinition. - */ - boolean isRequired() { - return _isRequired; - } - - /** - * Method to set the required flag of AttributeDefinition. - */ - void setRequired(boolean isRequired) { - this._isRequired = isRequired; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getOptionLabels() - */ - public String[] getOptionLabels() { - - if ((_labels == null) || (_labels.size() == 0)) { - return null; - } - - String[] returnedLabels = new String[_labels.size()]; - Enumeration labelKeys = _labels.elements(); - int i = 0; - while (labelKeys.hasMoreElements()) { - String labelKey = labelKeys.nextElement(); - returnedLabels[i] = getLocalized(labelKey); - i++; - } - return returnedLabels; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getOptionValues() - */ - public String[] getOptionValues() { - - if ((_values == null) || (_values.size() == 0)) { - return null; - } - - return _values.toArray(new String[_values.size()]); - } - - /** - * Method to set the Option values of AttributeDefinition. - */ - void setOption(Vector labels, Vector values, boolean needValidation) { - if ((labels == null) || (values == null)) { - logger.log(LogService.LOG_ERROR, "AttributeDefinitionImpl.setOption(Vector, Vector, boolean) " + MetaTypeMsg.NULL_OPTIONS); //$NON-NLS-1$ - return; - } - if (labels.size() != values.size()) { - logger.log(LogService.LOG_ERROR, "AttributeDefinitionImpl.setOption(Vector, Vector, boolean) " + MetaTypeMsg.INCONSISTENT_OPTIONS); //$NON-NLS-1$ - return; - } - _labels = labels; - _values = values; - if (needValidation) { - for (int index = 0; index < _values.size(); index++) { - ValueTokenizer vt = new ValueTokenizer(_values.get(index), logger); - _values.set(index, vt.getValuesAsString()); - String reason = vt.validate(this); - if ((reason != null) && reason.length() > 0) { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_OPTIONS, _values.get(index), reason)); - _labels.remove(index); - _values.remove(index); - index--; // Because this one has been removed. - } - } - } - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.AttributeDefinition#getDefaultValue() - */ - public String[] getDefaultValue() { - return _defaults; - } - - /** - * Method to set the default value of AttributeDefinition. - * The given parameter is a comma delimited list needed to be parsed. - */ - void setDefaultValue(String defaults_str, boolean needValidation) { - ValueTokenizer vt = new ValueTokenizer(defaults_str, logger); - String reason = vt.validate(this); - if ((reason != null) && reason.length() > 0) { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_DEFAULTS, vt.getValuesAsString(), reason)); - return; - } - setDefaultValue(vt.getValuesAsArray()); - } - - /** - * Method to set the default value of AttributeDefinition. - * The given parameter is a String array of multi values. - */ - void setDefaultValue(String[] defaults) { - _defaults = defaults; - } - - /** - * Method to set the validation value - min of AttributeDefinition. - */ - void setMinValue(Object minValue) { - this._minValue = minValue; - } - - /** - * Method to set the validation value - max of AttributeDefinition. - */ - void setMaxValue(Object maxValue) { - this._maxValue = maxValue; - } - - /* - * (non-Javadoc) - * In order to be valid, a value must pass all of the following tests. - * (1) The value must not be null. - * (2) The value must be convertible into the attribute definition's type. - * (3) The following relation must hold: min <= value <= max, if either min or max was specified. - * (4) If options were specified, the value must be equal to one of them. - * - * Note this method will never return null to indicate there's no validation - * present. The type compatibility check can always be performed. - * - * @see org.osgi.service.metatype.AttributeDefinition#validate(java.lang.String) - */ - public String validate(String value) { - ValueTokenizer vt = new ValueTokenizer(value, logger); - return vt.validate(this); - } - - public Map getExtensionAttributes(String schema) { - return helper.getExtensionAttributes(schema); - } - - public Set getExtensionUris() { - return helper.getExtensionUris(); - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.EquinoxAttributeDefinition; + +import java.util.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.service.log.LogService; + +/** + * Implementation of AttributeDefintion + */ +public class AttributeDefinitionImpl extends LocalizationElement implements EquinoxAttributeDefinition, Cloneable { + + String _name; + String _id; + String _description; + int _cardinality = 0; + int _dataType; + Object _minValue = null; + Object _maxValue = null; + boolean _isRequired = true; + + String[] _defaults = null; + Vector _values = new Vector(7); + Vector _labels = new Vector(7); + + private final LogService logger; + private final ExtendableHelper helper; + + /** + * Constructor of class AttributeDefinitionImpl. + */ + public AttributeDefinitionImpl(String id, String name, String description, int type, int cardinality, Object min, Object max, boolean isRequired, String localization, LogService logger, Map> extensionAttributes) { + this(id, name, description, type, cardinality, min, max, isRequired, localization, logger, new ExtendableHelper(extensionAttributes)); + } + + private AttributeDefinitionImpl(String id, String name, String description, int type, int cardinality, Object min, Object max, boolean isRequired, String localization, LogService logger, ExtendableHelper helper) { + this._id = id; + this._name = name; + this._description = description; + this._dataType = type; + this._cardinality = cardinality; + this._minValue = min; + this._maxValue = max; + this._isRequired = isRequired; + this._localization = localization; + this.logger = logger; + this.helper = helper; + } + + /* + * + */ + public synchronized Object clone() { + + AttributeDefinitionImpl ad = new AttributeDefinitionImpl(_id, _name, _description, _dataType, _cardinality, _minValue, _maxValue, _isRequired, _localization, logger, helper); + + if (_defaults != null) { + ad.setDefaultValue(_defaults.clone()); + } + if ((_labels != null) && (_values != null)) { + @SuppressWarnings("unchecked") + Vector labels = (Vector) _labels.clone(); + @SuppressWarnings("unchecked") + Vector values = (Vector) _values.clone(); + ad.setOption(labels, values, false); + } + + return ad; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getName() + */ + public String getName() { + return getLocalized(_name); + } + + /** + * Method to set the name of AttributeDefinition. + */ + void setName(String name) { + this._name = name; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getID() + */ + public String getID() { + return _id; + } + + /** + * Method to set the ID of AttributeDefinition. + */ + void setID(String id) { + this._id = id; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getDescription() + */ + public String getDescription() { + return getLocalized(_description); + } + + /** + * Method to set the description of AttributeDefinition. + */ + void setDescription(String description) { + this._description = description; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getCardinality() + */ + public int getCardinality() { + return _cardinality; + } + + /** + * Method to set the cardinality of AttributeDefinition. + */ + void setCardinality(int cardinality) { + this._cardinality = cardinality; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getType() + */ + public int getType() { + return _dataType; + } + + /** + * Method to set the data type of AttributeDefinition. + */ + void setType(int type) { + this._dataType = type; + } + + /** + * Method to get the required flag of AttributeDefinition. + */ + boolean isRequired() { + return _isRequired; + } + + /** + * Method to set the required flag of AttributeDefinition. + */ + void setRequired(boolean isRequired) { + this._isRequired = isRequired; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getOptionLabels() + */ + public String[] getOptionLabels() { + + if ((_labels == null) || (_labels.size() == 0)) { + return null; + } + + String[] returnedLabels = new String[_labels.size()]; + Enumeration labelKeys = _labels.elements(); + int i = 0; + while (labelKeys.hasMoreElements()) { + String labelKey = labelKeys.nextElement(); + returnedLabels[i] = getLocalized(labelKey); + i++; + } + return returnedLabels; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getOptionValues() + */ + public String[] getOptionValues() { + + if ((_values == null) || (_values.size() == 0)) { + return null; + } + + return _values.toArray(new String[_values.size()]); + } + + /** + * Method to set the Option values of AttributeDefinition. + */ + void setOption(Vector labels, Vector values, boolean needValidation) { + if ((labels == null) || (values == null)) { + logger.log(LogService.LOG_ERROR, "AttributeDefinitionImpl.setOption(Vector, Vector, boolean) " + MetaTypeMsg.NULL_OPTIONS); //$NON-NLS-1$ + return; + } + if (labels.size() != values.size()) { + logger.log(LogService.LOG_ERROR, "AttributeDefinitionImpl.setOption(Vector, Vector, boolean) " + MetaTypeMsg.INCONSISTENT_OPTIONS); //$NON-NLS-1$ + return; + } + _labels = labels; + _values = values; + if (needValidation) { + for (int index = 0; index < _values.size(); index++) { + ValueTokenizer vt = new ValueTokenizer(_values.get(index), logger); + _values.set(index, vt.getValuesAsString()); + String reason = vt.validate(this); + if ((reason != null) && reason.length() > 0) { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_OPTIONS, _values.get(index), reason)); + _labels.remove(index); + _values.remove(index); + index--; // Because this one has been removed. + } + } + } + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.AttributeDefinition#getDefaultValue() + */ + public String[] getDefaultValue() { + return _defaults; + } + + /** + * Method to set the default value of AttributeDefinition. + * The given parameter is a comma delimited list needed to be parsed. + */ + void setDefaultValue(String defaults_str, boolean needValidation) { + ValueTokenizer vt = new ValueTokenizer(defaults_str, logger); + String reason = vt.validate(this); + if ((reason != null) && reason.length() > 0) { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_DEFAULTS, vt.getValuesAsString(), reason)); + return; + } + setDefaultValue(vt.getValuesAsArray()); + } + + /** + * Method to set the default value of AttributeDefinition. + * The given parameter is a String array of multi values. + */ + void setDefaultValue(String[] defaults) { + _defaults = defaults; + } + + /** + * Method to set the validation value - min of AttributeDefinition. + */ + void setMinValue(Object minValue) { + this._minValue = minValue; + } + + /** + * Method to set the validation value - max of AttributeDefinition. + */ + void setMaxValue(Object maxValue) { + this._maxValue = maxValue; + } + + /* + * (non-Javadoc) + * In order to be valid, a value must pass all of the following tests. + * (1) The value must not be null. + * (2) The value must be convertible into the attribute definition's type. + * (3) The following relation must hold: min <= value <= max, if either min or max was specified. + * (4) If options were specified, the value must be equal to one of them. + * + * Note this method will never return null to indicate there's no validation + * present. The type compatibility check can always be performed. + * + * @see org.osgi.service.metatype.AttributeDefinition#validate(java.lang.String) + */ + public String validate(String value) { + ValueTokenizer vt = new ValueTokenizer(value, logger); + return vt.validate(this); + } + + public Map getExtensionAttributes(String schema) { + return helper.getExtensionAttributes(schema); + } + + public Set getExtensionUris() { + return helper.getExtensionUris(); + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/DataParser.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/DataParser.java index f7cb3296c..e8d20a8e1 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/DataParser.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/DataParser.java @@ -1,849 +1,849 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import java.io.*; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URL; -import java.util.*; -import javax.xml.parsers.SAXParser; -import org.eclipse.osgi.util.NLS; -import org.osgi.framework.Bundle; -import org.osgi.service.log.LogService; -import org.osgi.service.metatype.AttributeDefinition; -import org.xml.sax.*; -import org.xml.sax.helpers.DefaultHandler; - -/** - * Meta XML Data Parser - */ -public class DataParser { - private static final String METADATA = "MetaData"; //$NON-NLS-1$ - private static final String LOCALIZATION = "localization"; //$NON-NLS-1$ - private static final String OCD = "OCD"; //$NON-NLS-1$ - private static final String ICON = "Icon"; //$NON-NLS-1$ - private static final String AD = "AD"; //$NON-NLS-1$ - private static final String CARDINALITY = "cardinality"; //$NON-NLS-1$ - private static final String OPTION = "Option"; //$NON-NLS-1$ - private static final String LABEL = "label"; //$NON-NLS-1$ - private static final String VALUE = "value"; //$NON-NLS-1$ - private static final String MIN = "min"; //$NON-NLS-1$ - private static final String MAX = "max"; //$NON-NLS-1$ - private static final String TYPE = "type"; //$NON-NLS-1$ - private static final String SIZE = "size"; //$NON-NLS-1$ - private static final String ID = "id"; //$NON-NLS-1$ - private static final String NAME = "name"; //$NON-NLS-1$ - private static final String DESCRIPTION = "description"; //$NON-NLS-1$ - private static final String RESOURCE = "resource"; //$NON-NLS-1$ - private static final String PID = "pid"; //$NON-NLS-1$ - private static final String DEFAULT = "default"; //$NON-NLS-1$ - private static final String ADREF = "adref"; //$NON-NLS-1$ - private static final String CONTENT = "content"; //$NON-NLS-1$ - private static final String FACTORY = "factoryPid"; //$NON-NLS-1$ - private static final String BUNDLE = "bundle"; //$NON-NLS-1$ - private static final String OPTIONAL = "optional"; //$NON-NLS-1$ - private static final String OBJECT = "Object"; //$NON-NLS-1$ - private static final String OCDREF = "ocdref"; //$NON-NLS-1$ - private static final String ATTRIBUTE = "Attribute"; //$NON-NLS-1$ - private static final String DESIGNATE = "Designate"; //$NON-NLS-1$ - private static final String MERGE = "merge"; //$NON-NLS-1$ - private static final String REQUIRED = "required"; //$NON-NLS-1$ - - private static final String INTEGER = "Integer"; //$NON-NLS-1$ - private static final String STRING = "String"; //$NON-NLS-1$ - private static final String FLOAT = "Float"; //$NON-NLS-1$ - private static final String DOUBLE = "Double"; //$NON-NLS-1$ - private static final String BYTE = "Byte"; //$NON-NLS-1$ - private static final String LONG = "Long"; //$NON-NLS-1$ - private static final String CHAR = "Char"; //$NON-NLS-1$ - private static final String BOOLEAN = "Boolean"; //$NON-NLS-1$ - private static final String SHORT = "Short"; //$NON-NLS-1$ - private static final String PASSWORD = "Password"; //$NON-NLS-1$ - - protected Bundle _dp_bundle; - protected URL _dp_url; - protected SAXParser _dp_parser; - protected XMLReader _dp_xmlReader; - - // DesignateHanders in DataParser class - Vector _dp_designateHandlers = new Vector(7); - // ObjectClassDefinitions in DataParser class w/ corresponding reference keys - Hashtable _dp_OCDs = new Hashtable(7); - // Localization in DataParser class - String _dp_localization; - - // Default visibility to avoid a plethora of synthetic accessor method warnings. - final LogService logger; - final Collection designates = new ArrayList(7); - - /* - * Constructor of class DataParser. - */ - public DataParser(Bundle bundle, URL url, SAXParser parser, LogService logger) { - - this._dp_bundle = bundle; - this._dp_url = url; - this._dp_parser = parser; - this.logger = logger; - } - - /* - * Main method to parse specific MetaData file. - */ - public Collection doParse() throws IOException, SAXException { - _dp_xmlReader = _dp_parser.getXMLReader(); - _dp_xmlReader.setContentHandler(new RootHandler()); - _dp_xmlReader.setErrorHandler(new MyErrorHandler(System.err)); - InputStream is = _dp_url.openStream(); - InputSource isource = new InputSource(is); - logger.log(LogService.LOG_DEBUG, "Starting to parse " + _dp_url); //$NON-NLS-1$ - _dp_xmlReader.parse(isource); - return designates; - } - - /* - * Convert String for expected data type. - */ - static Object convert(String value, int type) { - - if (value == null) { - return null; - } - - switch (type) { - // PASSWORD should be treated like STRING. - case AttributeDefinition.PASSWORD : - case AttributeDefinition.STRING : - // Both the min and max of STRING are Integers. - return new Integer(value); - case AttributeDefinition.LONG : - return new Long(value); - case AttributeDefinition.INTEGER : - return new Integer(value); - case AttributeDefinition.SHORT : - return new Short(value); - case AttributeDefinition.CHARACTER : - return new Character(value.charAt(0)); - case AttributeDefinition.BYTE : - return new Byte(value); - case AttributeDefinition.DOUBLE : - return new Double(value); - case AttributeDefinition.FLOAT : - return new Float(value); - case AttributeDefinition.BIGINTEGER : - return new BigInteger(value); - case AttributeDefinition.BIGDECIMAL : - return new BigDecimal(value); - case AttributeDefinition.BOOLEAN : - return new Boolean(value); - default : - // Unknown data type - return null; - } - } - - /** - * Abstract of all Handlers. - */ - private class AbstractHandler extends DefaultHandler { - protected ContentHandler _doc_handler; - protected boolean _isParsedDataValid = true; - protected Map> extensionAttributes = new HashMap>(); - - public AbstractHandler(ContentHandler parentHandler) { - this._doc_handler = parentHandler; - _dp_xmlReader.setContentHandler(this); - } - - public void endElement(String namespaceURI, String localName, String qName) { - finished(); - // Let parent resume handling SAX events - _dp_xmlReader.setContentHandler(_doc_handler); - } - - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - throw new SAXException(NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, qName)); - } - - public void characters(char[] buf, int start, int end) throws SAXException { - String s = new String(buf, start, end).trim(); - if (s.length() > 0) { - throw new SAXException(NLS.bind(MetaTypeMsg.UNEXPECTED_TEXT, s)); - } - } - - protected void collectExtensionAttributes(Attributes attributes) { - for (int i = 0; i < attributes.getLength(); i++) { - String key = attributes.getURI(i); - if (key.length() == 0 || key.startsWith("http://www.osgi.org/xmlns/metatype/v")) //$NON-NLS-1$ - continue; - Map value = extensionAttributes.get(key); - if (value == null) { - value = new HashMap(); - extensionAttributes.put(key, value); - } - value.put(getName(attributes.getLocalName(i), attributes.getQName(i)), attributes.getValue(i)); - } - } - - /** - * Called when this element and all elements nested into it have been - * handled. - */ - protected void finished() { - // do nothing by default - } - } - - /** - * Handler for the root element. - */ - private class RootHandler extends DefaultHandler { - - public RootHandler() { - super(); - } - - public void startElement(String uri, String localName, String qName, Attributes attributes) { - - logger.log(LogService.LOG_DEBUG, "Here is AbstractHandler:startElement():" //$NON-NLS-1$ - + qName); - String name = getName(localName, qName); - if (name.equalsIgnoreCase(METADATA)) { - new MetaDataHandler(this).init(name, attributes); - } else { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); - } - } - - public void setDocumentLocator(Locator locator) { - // do nothing - } - } - - /** - * Handler for the MetaData element. - */ - private class MetaDataHandler extends AbstractHandler { - - public MetaDataHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes attributes) { - - logger.log(LogService.LOG_DEBUG, "Here is MetaDataHandler():init()"); //$NON-NLS-1$ - _dp_localization = attributes.getValue(LOCALIZATION); - if (_dp_localization == null) { - // Not a problem, because LOCALIZATION is an optional attribute. - } - // The global variable "_dp_localization" will be used within - // OcdHandler and AttributeDefinitionHandler later. - } - - public void startElement(String uri, String localName, String qName, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is MetaDataHandler:startElement():" //$NON-NLS-1$ - + qName); - String name = getName(localName, qName); - if (name.equalsIgnoreCase(DESIGNATE)) { - DesignateHandler designateHandler = new DesignateHandler(this); - designateHandler.init(name, atts); - if (designateHandler._isParsedDataValid) { - _dp_designateHandlers.addElement(designateHandler); - } - } else if (name.equalsIgnoreCase(OCD)) { - OcdHandler ocdHandler = new OcdHandler(this); - ocdHandler.init(name, atts, _dp_OCDs); - } else { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); - } - } - - protected void finished() { - - logger.log(LogService.LOG_DEBUG, "Here is MetaDataHandler():finished()"); //$NON-NLS-1$ - if (_dp_designateHandlers.size() == 0) { - // Schema defines at least one DESIGNATE is required. - _isParsedDataValid = false; - logger.log(LogService.LOG_WARNING, "DataParser.finished() " + NLS.bind(MetaTypeMsg.MISSING_ELEMENT, DESIGNATE)); //$NON-NLS-1$ - return; - } - Enumeration designateHandlerKeys = _dp_designateHandlers.elements(); - while (designateHandlerKeys.hasMoreElements()) { - DesignateHandler dh = designateHandlerKeys.nextElement(); - - ObjectClassDefinitionImpl ocd = _dp_OCDs.get(dh._ocdref); - if (ocd != null) { - designates.add(new Designate.Builder(ocd).bundle(dh._bundle_val).factoryPid(dh._factory_val).merge(dh._merge_val).pid(dh._pid_val).optional(dh._optional_val).build()); - } else { - logger.log(LogService.LOG_ERROR, "DataParser.finished() " + NLS.bind(MetaTypeMsg.OCD_ID_NOT_FOUND, dh._ocdref)); //$NON-NLS-1$ - - } - } - } - } - - /** - * Handler for the ObjectClassDefinition element. - */ - private class OcdHandler extends AbstractHandler { - - Hashtable _parent_OCDs_hashtable; - // This ID "_refID" is only used for reference by Designate element, - // not the PID or FPID of this OCD. - String _refID; - ObjectClassDefinitionImpl _ocd; - Vector _ad_vector = new Vector(7); - - public OcdHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts, Hashtable ocds_hashtable) { - - logger.log(LogService.LOG_DEBUG, "Here is OcdHandler():init()"); //$NON-NLS-1$ - _parent_OCDs_hashtable = ocds_hashtable; - collectExtensionAttributes(atts); - String ocd_name_val = atts.getValue(NAME); - if (ocd_name_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Hashtable) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, NAME, name)); //$NON-NLS-1$ - return; - } - - String ocd_description_val = atts.getValue(DESCRIPTION); - if (ocd_description_val == null) { - // Not a problem, because DESCRIPTION is an optional attribute. - } - - _refID = atts.getValue(ID); - if (_refID == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Hashtable) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, ID, name)); //$NON-NLS-1$ - return; - } - - _ocd = new ObjectClassDefinitionImpl(ocd_name_val, ocd_description_val, _refID, _dp_localization, extensionAttributes); - } - - public void startElement(String uri, String localName, String qName, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is OcdHandler:startElement():" //$NON-NLS-1$ - + qName); - if (!_isParsedDataValid) - return; - - String name = getName(localName, qName); - if (name.equalsIgnoreCase(AD)) { - AttributeDefinitionHandler attributeDefHandler = new AttributeDefinitionHandler(this); - attributeDefHandler.init(name, atts, _ad_vector); - } else if (name.equalsIgnoreCase(ICON)) { - IconHandler iconHandler = new IconHandler(this); - iconHandler.init(name, atts); - if (iconHandler._isParsedDataValid) { - // Because XML schema allows at most one icon for - // one OCD, if more than one icons are read from - // MetaData, then only the final icon will be kept. - _ocd.setIcon(iconHandler._icon); - } - } else { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); - } - } - - protected void finished() { - - logger.log(LogService.LOG_DEBUG, "Here is OcdHandler():finished()"); //$NON-NLS-1$ - if (!_isParsedDataValid) - return; - - if (_ad_vector.size() == 0) { - // Schema defines at least one AD is required. - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.finished() " + NLS.bind(MetaTypeMsg.MISSING_ELEMENT, AD, _refID)); //$NON-NLS-1$ - return; - } - // OCD gets all parsed ADs. - Enumeration adKey = _ad_vector.elements(); - while (adKey.hasMoreElements()) { - AttributeDefinitionImpl ad = adKey.nextElement(); - _ocd.addAttributeDefinition(ad, ad._isRequired); - } - - _parent_OCDs_hashtable.put(_refID, _ocd); - } - } - - /** - * Handler for the Icon element. - */ - private class IconHandler extends AbstractHandler { - - Icon _icon; - - public IconHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is IconHandler:init()"); //$NON-NLS-1$ - String icon_resource_val = atts.getValue(RESOURCE); - if (icon_resource_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, RESOURCE, name)); //$NON-NLS-1$ - return; - } - - String icon_size_val = atts.getValue(SIZE); - if (icon_size_val == null) { - // Not a problem, because SIZE is an optional attribute. - icon_size_val = "0"; //$NON-NLS-1$ - } else if (icon_size_val.equalsIgnoreCase("")) { //$NON-NLS-1$ - icon_size_val = "0"; //$NON-NLS-1$ - } - - _icon = new Icon(icon_resource_val, Integer.parseInt(icon_size_val), _dp_bundle); - } - } - - /** - * Handler for the Attribute element. - */ - private class AttributeDefinitionHandler extends AbstractHandler { - - AttributeDefinitionImpl _ad; - int _dataType; - - Vector _parent_ADs_vector; - Vector _optionLabel_vector = new Vector(7); - Vector _optionValue_vector = new Vector(7); - - public AttributeDefinitionHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts, Vector ad_vector) { - - logger.log(LogService.LOG_DEBUG, "Here is AttributeDefinitionHandler():init()"); //$NON-NLS-1$ - _parent_ADs_vector = ad_vector; - collectExtensionAttributes(atts); - String ad_name_val = atts.getValue(NAME); - if (ad_name_val == null) { - // Not a problem, because NAME is an optional attribute. - } - - String ad_description_val = atts.getValue(DESCRIPTION); - if (ad_description_val == null) { - // Not a problem, because DESCRIPTION is an optional attribute. - } - - String ad_id_val = atts.getValue(ID); - if (ad_id_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Vector) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, ID, name)); //$NON-NLS-1$ - return; - } - - String ad_type_val = atts.getValue(TYPE); - if (ad_type_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Vector) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, TYPE, name)); //$NON-NLS-1$ - return; - } - if (ad_type_val.equalsIgnoreCase(STRING)) { - _dataType = AttributeDefinition.STRING; - } else if (ad_type_val.equalsIgnoreCase(LONG)) { - _dataType = AttributeDefinition.LONG; - } else if (ad_type_val.equalsIgnoreCase(DOUBLE)) { - _dataType = AttributeDefinition.DOUBLE; - } else if (ad_type_val.equalsIgnoreCase(FLOAT)) { - _dataType = AttributeDefinition.FLOAT; - } else if (ad_type_val.equalsIgnoreCase(INTEGER)) { - _dataType = AttributeDefinition.INTEGER; - } else if (ad_type_val.equalsIgnoreCase(BYTE)) { - _dataType = AttributeDefinition.BYTE; - } else if (ad_type_val.equalsIgnoreCase(CHAR)) { - _dataType = AttributeDefinition.CHARACTER; - } else if (ad_type_val.equalsIgnoreCase(BOOLEAN)) { - _dataType = AttributeDefinition.BOOLEAN; - } else if (ad_type_val.equalsIgnoreCase(SHORT)) { - _dataType = AttributeDefinition.SHORT; - } else if (ad_type_val.equalsIgnoreCase(PASSWORD)) { - _dataType = AttributeDefinition.PASSWORD; - } else { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Vector) " + NLS.bind(MetaTypeMsg.INVALID_TYPE, new Object[] {ad_type_val, _dp_url, _dp_bundle.getBundleId()})); //$NON-NLS-1$ - return; - } - - String ad_cardinality_str = atts.getValue(CARDINALITY); - int ad_cardinality_val = 0; - if (ad_cardinality_str == null) { - // Not a problem, because CARDINALITY is an optional attribute. - // And the default value is 0. - } else { - ad_cardinality_val = Integer.parseInt(ad_cardinality_str); - } - - String ad_min_val = atts.getValue(MIN); - if (ad_min_val == null) { - // Not a problem, because MIN is an optional attribute. - } - - String ad_max_val = atts.getValue(MAX); - if (ad_max_val == null) { - // Not a problem, because MAX is an optional attribute. - } - - String ad_defaults_str = atts.getValue(DEFAULT); - if (ad_defaults_str == null) { - // Not a problem, because DEFAULT is an optional attribute. - } - - String ad_required_val = atts.getValue(REQUIRED); - if (ad_required_val == null) { - // Not a problem, because REQUIRED is an optional attribute. - // And the default value is 'true'. - ad_required_val = Boolean.TRUE.toString(); - } - - _ad = new AttributeDefinitionImpl(ad_id_val, ad_name_val, ad_description_val, _dataType, ad_cardinality_val, convert(ad_min_val, _dataType), convert(ad_max_val, _dataType), Boolean.valueOf(ad_required_val).booleanValue(), _dp_localization, logger, extensionAttributes); - - if (ad_defaults_str != null) { - _ad.setDefaultValue(ad_defaults_str, true); - } - } - - public void startElement(String uri, String localName, String qName, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is AttributeDefinitionHandler:startElement():" //$NON-NLS-1$ - + qName); - if (!_isParsedDataValid) - return; - - String name = getName(localName, qName); - if (name.equalsIgnoreCase(OPTION)) { - OptionHandler optionHandler = new OptionHandler(this); - optionHandler.init(name, atts); - if (optionHandler._isParsedDataValid) { - // Only add valid Option - _optionLabel_vector.addElement(optionHandler._label_val); - _optionValue_vector.addElement(optionHandler._value_val); - } - } else { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); - } - } - - protected void finished() { - - logger.log(LogService.LOG_DEBUG, "Here is AttributeDefinitionHandler():finished()"); //$NON-NLS-1$ - if (!_isParsedDataValid) - return; - - _ad.setOption(_optionLabel_vector, _optionValue_vector, true); - _parent_ADs_vector.addElement(_ad); - } - } - - /** - * Handler for the Option element. - */ - private class OptionHandler extends AbstractHandler { - - String _label_val; - String _value_val; - - public OptionHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is OptionHandler:init()"); //$NON-NLS-1$ - _label_val = atts.getValue(LABEL); - if (_label_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, LABEL, name)); //$NON-NLS-1$ - return; - } - - _value_val = atts.getValue(VALUE); - if (_value_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, VALUE, name)); //$NON-NLS-1$ - return; - } - } - } - - // /** - // * Handler for the Simple Value element. - // */ - // private class SimpleValueHandler extends AbstractHandler { - // - // StringBuffer _buffer = new StringBuffer(); - // Vector _parent_value_vector; - // String _elementName; - // - // public SimpleValueHandler(ContentHandler handler) { - // super(handler); - // } - // - // public void init(String name, Attributes atts, Vector value_vector) - // throws SAXException { - // - // Logging.log(LogService.LOG_DEBUG, - // "Here is SimpleValueHandler():init()"); //$NON-NLS-1$ - // _elementName = name; - // _parent_value_vector = value_vector; - // } - // - // protected void finished() throws SAXException { - // - // Logging.log(LogService.LOG_DEBUG, - // "Here is SimpleValueHandler():finished()"); //$NON-NLS-1$ - // if (_parent_value_vector != null) { - // _parent_value_vector.addElement(_buffer.toString()); - // } - // } - // - // public void characters(char buf[], int offset, int len) - // throws SAXException { - // - // Logging.log(LogService.LOG_DEBUG, - // "Here is SimpleValueHandler(" //$NON-NLS-1$ - // + _elementName - // + "):characters():[" //$NON-NLS-1$ - // + new String(buf, offset, len) - // + "]"); //$NON-NLS-1$ - // _buffer.append(new String(buf, offset, len)); - // } - // } - - /** - * Handler for the Designate element. - */ - class DesignateHandler extends AbstractHandler { - - String _pid_val = null; - String _factory_val = null; - String _bundle_val = null; // Only used by RFC94 - boolean _optional_val = false; // Only used by RFC94 - boolean _merge_val = false; // Only used by RFC94 - - // Referenced OCD ID - String _ocdref; - - public DesignateHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is DesignateHandler():init()"); //$NON-NLS-1$ - _pid_val = atts.getValue(PID); - _factory_val = atts.getValue(FACTORY); - if (_pid_val == null && _factory_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, MetaTypeMsg.MISSING_DESIGNATE_PID_AND_FACTORYPID); - return; - } - - _bundle_val = atts.getValue(BUNDLE); - if (_bundle_val == null) { - // Not a problem because BUNDLE is an optional attribute. - } - - String optional_str = atts.getValue(OPTIONAL); - if (optional_str == null) { - // Not a problem, because OPTIONAL is an optional attribute. - // The default value is "false". - _optional_val = false; - } else { - _optional_val = Boolean.valueOf(optional_str).booleanValue(); - } - - String merge_str = atts.getValue(MERGE); - if (merge_str == null) { - // Not a problem, because MERGE is an optional attribute. - // The default value is "false". - _merge_val = false; - } else { - _merge_val = Boolean.valueOf(merge_str).booleanValue(); - } - } - - public void startElement(String uri, String localName, String qName, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is DesignateHandler:startElement():" //$NON-NLS-1$ - + qName); - if (!_isParsedDataValid) - return; - - String name = getName(localName, qName); - if (name.equalsIgnoreCase(OBJECT)) { - ObjectHandler objectHandler = new ObjectHandler(this); - objectHandler.init(name, atts); - if (objectHandler._isParsedDataValid) { - _ocdref = objectHandler._ocdref; - } - } else { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); - } - } - - protected void finished() { - - logger.log(LogService.LOG_DEBUG, "Here is DesignateHandler():finished()"); //$NON-NLS-1$ - if (!_isParsedDataValid) - return; - - if (_ocdref == null) { - _isParsedDataValid = false; - // Schema defines at least one OBJECT is required. - logger.log(LogService.LOG_ERROR, "DataParser.finished() " + NLS.bind(MetaTypeMsg.MISSING_ELEMENT, OBJECT, _pid_val)); //$NON-NLS-1$ - return; - - } - } - } - - /** - * Handler for the Object element. - */ - private class ObjectHandler extends AbstractHandler { - - String _ocdref; - - public ObjectHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is ObjectHandler():init()"); //$NON-NLS-1$ - _ocdref = atts.getValue(OCDREF); - if (_ocdref == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, OCDREF, name)); //$NON-NLS-1$ - return; - } - } - - public void startElement(String uri, String localName, String qName, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is ObjectHandler:startElement():" //$NON-NLS-1$ - + qName); - if (!_isParsedDataValid) - return; - - String name = getName(localName, qName); - if (name.equalsIgnoreCase(ATTRIBUTE)) { - AttributeHandler attributeHandler = new AttributeHandler(this); - attributeHandler.init(name, atts); - // The ATTRIBUTE element is only used by RFC94, do nothing for it here. - } else { - logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); - } - } - } - - /** - * Handler for the Attribute element. - * - * This Handler is only used by RFC94. - */ - private class AttributeHandler extends AbstractHandler { - - String _adref_val; - String _content_val; - - public AttributeHandler(ContentHandler handler) { - super(handler); - } - - public void init(String name, Attributes atts) { - - logger.log(LogService.LOG_DEBUG, "Here is AttributeHandler():init()"); //$NON-NLS-1$ - _adref_val = atts.getValue(ADREF); - if (_adref_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, ADREF, name)); //$NON-NLS-1$ - return; - } - - _content_val = atts.getValue(CONTENT); - if (_content_val == null) { - _isParsedDataValid = false; - logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, CONTENT, name)); //$NON-NLS-1$ - return; - } - } - } - - /** - * Error Handler to report errors and warnings - */ - private static class MyErrorHandler implements ErrorHandler { - - /** Error handler output goes here */ - private PrintStream _out; - - MyErrorHandler(PrintStream out) { - this._out = out; - } - - /** - * Returns a string describing parse exception details - */ - private String getParseExceptionInfo(SAXParseException spe) { - String systemId = spe.getSystemId(); - if (systemId == null) { - systemId = "null"; //$NON-NLS-1$ - } - String info = "URI=" + systemId + //$NON-NLS-1$ - " Line=" + spe.getLineNumber() + //$NON-NLS-1$ - ": " + spe.getMessage(); //$NON-NLS-1$ - - return info; - } - - // The following methods are standard SAX ErrorHandler methods. - // See SAX documentation for more info. - - public void warning(SAXParseException spe) { - _out.println("Warning: " + getParseExceptionInfo(spe)); //$NON-NLS-1$ - } - - public void error(SAXParseException spe) throws SAXException { - String message = "Error: " + getParseExceptionInfo(spe); //$NON-NLS-1$ - throw new SAXException(message); - } - - public void fatalError(SAXParseException spe) throws SAXException { - String message = "Fatal Error: " + getParseExceptionInfo(spe); //$NON-NLS-1$ - throw new SAXException(message); - } - } - - public static String getName(String localName, String qName) { - if (localName != null && localName.length() > 0) { - return localName; - } - - int nameSpaceIndex = qName.indexOf(":"); //$NON-NLS-1$ - return nameSpaceIndex == -1 ? qName : qName.substring(nameSpaceIndex + 1); - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URL; +import java.util.*; +import javax.xml.parsers.SAXParser; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.Bundle; +import org.osgi.service.log.LogService; +import org.osgi.service.metatype.AttributeDefinition; +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Meta XML Data Parser + */ +public class DataParser { + private static final String METADATA = "MetaData"; //$NON-NLS-1$ + private static final String LOCALIZATION = "localization"; //$NON-NLS-1$ + private static final String OCD = "OCD"; //$NON-NLS-1$ + private static final String ICON = "Icon"; //$NON-NLS-1$ + private static final String AD = "AD"; //$NON-NLS-1$ + private static final String CARDINALITY = "cardinality"; //$NON-NLS-1$ + private static final String OPTION = "Option"; //$NON-NLS-1$ + private static final String LABEL = "label"; //$NON-NLS-1$ + private static final String VALUE = "value"; //$NON-NLS-1$ + private static final String MIN = "min"; //$NON-NLS-1$ + private static final String MAX = "max"; //$NON-NLS-1$ + private static final String TYPE = "type"; //$NON-NLS-1$ + private static final String SIZE = "size"; //$NON-NLS-1$ + private static final String ID = "id"; //$NON-NLS-1$ + private static final String NAME = "name"; //$NON-NLS-1$ + private static final String DESCRIPTION = "description"; //$NON-NLS-1$ + private static final String RESOURCE = "resource"; //$NON-NLS-1$ + private static final String PID = "pid"; //$NON-NLS-1$ + private static final String DEFAULT = "default"; //$NON-NLS-1$ + private static final String ADREF = "adref"; //$NON-NLS-1$ + private static final String CONTENT = "content"; //$NON-NLS-1$ + private static final String FACTORY = "factoryPid"; //$NON-NLS-1$ + private static final String BUNDLE = "bundle"; //$NON-NLS-1$ + private static final String OPTIONAL = "optional"; //$NON-NLS-1$ + private static final String OBJECT = "Object"; //$NON-NLS-1$ + private static final String OCDREF = "ocdref"; //$NON-NLS-1$ + private static final String ATTRIBUTE = "Attribute"; //$NON-NLS-1$ + private static final String DESIGNATE = "Designate"; //$NON-NLS-1$ + private static final String MERGE = "merge"; //$NON-NLS-1$ + private static final String REQUIRED = "required"; //$NON-NLS-1$ + + private static final String INTEGER = "Integer"; //$NON-NLS-1$ + private static final String STRING = "String"; //$NON-NLS-1$ + private static final String FLOAT = "Float"; //$NON-NLS-1$ + private static final String DOUBLE = "Double"; //$NON-NLS-1$ + private static final String BYTE = "Byte"; //$NON-NLS-1$ + private static final String LONG = "Long"; //$NON-NLS-1$ + private static final String CHAR = "Char"; //$NON-NLS-1$ + private static final String BOOLEAN = "Boolean"; //$NON-NLS-1$ + private static final String SHORT = "Short"; //$NON-NLS-1$ + private static final String PASSWORD = "Password"; //$NON-NLS-1$ + + protected Bundle _dp_bundle; + protected URL _dp_url; + protected SAXParser _dp_parser; + protected XMLReader _dp_xmlReader; + + // DesignateHanders in DataParser class + Vector _dp_designateHandlers = new Vector(7); + // ObjectClassDefinitions in DataParser class w/ corresponding reference keys + Hashtable _dp_OCDs = new Hashtable(7); + // Localization in DataParser class + String _dp_localization; + + // Default visibility to avoid a plethora of synthetic accessor method warnings. + final LogService logger; + final Collection designates = new ArrayList(7); + + /* + * Constructor of class DataParser. + */ + public DataParser(Bundle bundle, URL url, SAXParser parser, LogService logger) { + + this._dp_bundle = bundle; + this._dp_url = url; + this._dp_parser = parser; + this.logger = logger; + } + + /* + * Main method to parse specific MetaData file. + */ + public Collection doParse() throws IOException, SAXException { + _dp_xmlReader = _dp_parser.getXMLReader(); + _dp_xmlReader.setContentHandler(new RootHandler()); + _dp_xmlReader.setErrorHandler(new MyErrorHandler(System.err)); + InputStream is = _dp_url.openStream(); + InputSource isource = new InputSource(is); + logger.log(LogService.LOG_DEBUG, "Starting to parse " + _dp_url); //$NON-NLS-1$ + _dp_xmlReader.parse(isource); + return designates; + } + + /* + * Convert String for expected data type. + */ + static Object convert(String value, int type) { + + if (value == null) { + return null; + } + + switch (type) { + // PASSWORD should be treated like STRING. + case AttributeDefinition.PASSWORD : + case AttributeDefinition.STRING : + // Both the min and max of STRING are Integers. + return new Integer(value); + case AttributeDefinition.LONG : + return new Long(value); + case AttributeDefinition.INTEGER : + return new Integer(value); + case AttributeDefinition.SHORT : + return new Short(value); + case AttributeDefinition.CHARACTER : + return new Character(value.charAt(0)); + case AttributeDefinition.BYTE : + return new Byte(value); + case AttributeDefinition.DOUBLE : + return new Double(value); + case AttributeDefinition.FLOAT : + return new Float(value); + case AttributeDefinition.BIGINTEGER : + return new BigInteger(value); + case AttributeDefinition.BIGDECIMAL : + return new BigDecimal(value); + case AttributeDefinition.BOOLEAN : + return new Boolean(value); + default : + // Unknown data type + return null; + } + } + + /** + * Abstract of all Handlers. + */ + private class AbstractHandler extends DefaultHandler { + protected ContentHandler _doc_handler; + protected boolean _isParsedDataValid = true; + protected Map> extensionAttributes = new HashMap>(); + + public AbstractHandler(ContentHandler parentHandler) { + this._doc_handler = parentHandler; + _dp_xmlReader.setContentHandler(this); + } + + public void endElement(String namespaceURI, String localName, String qName) { + finished(); + // Let parent resume handling SAX events + _dp_xmlReader.setContentHandler(_doc_handler); + } + + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + throw new SAXException(NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, qName)); + } + + public void characters(char[] buf, int start, int end) throws SAXException { + String s = new String(buf, start, end).trim(); + if (s.length() > 0) { + throw new SAXException(NLS.bind(MetaTypeMsg.UNEXPECTED_TEXT, s)); + } + } + + protected void collectExtensionAttributes(Attributes attributes) { + for (int i = 0; i < attributes.getLength(); i++) { + String key = attributes.getURI(i); + if (key.length() == 0 || key.startsWith("http://www.osgi.org/xmlns/metatype/v")) //$NON-NLS-1$ + continue; + Map value = extensionAttributes.get(key); + if (value == null) { + value = new HashMap(); + extensionAttributes.put(key, value); + } + value.put(getName(attributes.getLocalName(i), attributes.getQName(i)), attributes.getValue(i)); + } + } + + /** + * Called when this element and all elements nested into it have been + * handled. + */ + protected void finished() { + // do nothing by default + } + } + + /** + * Handler for the root element. + */ + private class RootHandler extends DefaultHandler { + + public RootHandler() { + super(); + } + + public void startElement(String uri, String localName, String qName, Attributes attributes) { + + logger.log(LogService.LOG_DEBUG, "Here is AbstractHandler:startElement():" //$NON-NLS-1$ + + qName); + String name = getName(localName, qName); + if (name.equalsIgnoreCase(METADATA)) { + new MetaDataHandler(this).init(name, attributes); + } else { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); + } + } + + public void setDocumentLocator(Locator locator) { + // do nothing + } + } + + /** + * Handler for the MetaData element. + */ + private class MetaDataHandler extends AbstractHandler { + + public MetaDataHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes attributes) { + + logger.log(LogService.LOG_DEBUG, "Here is MetaDataHandler():init()"); //$NON-NLS-1$ + _dp_localization = attributes.getValue(LOCALIZATION); + if (_dp_localization == null) { + // Not a problem, because LOCALIZATION is an optional attribute. + } + // The global variable "_dp_localization" will be used within + // OcdHandler and AttributeDefinitionHandler later. + } + + public void startElement(String uri, String localName, String qName, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is MetaDataHandler:startElement():" //$NON-NLS-1$ + + qName); + String name = getName(localName, qName); + if (name.equalsIgnoreCase(DESIGNATE)) { + DesignateHandler designateHandler = new DesignateHandler(this); + designateHandler.init(name, atts); + if (designateHandler._isParsedDataValid) { + _dp_designateHandlers.addElement(designateHandler); + } + } else if (name.equalsIgnoreCase(OCD)) { + OcdHandler ocdHandler = new OcdHandler(this); + ocdHandler.init(name, atts, _dp_OCDs); + } else { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); + } + } + + protected void finished() { + + logger.log(LogService.LOG_DEBUG, "Here is MetaDataHandler():finished()"); //$NON-NLS-1$ + if (_dp_designateHandlers.size() == 0) { + // Schema defines at least one DESIGNATE is required. + _isParsedDataValid = false; + logger.log(LogService.LOG_WARNING, "DataParser.finished() " + NLS.bind(MetaTypeMsg.MISSING_ELEMENT, DESIGNATE)); //$NON-NLS-1$ + return; + } + Enumeration designateHandlerKeys = _dp_designateHandlers.elements(); + while (designateHandlerKeys.hasMoreElements()) { + DesignateHandler dh = designateHandlerKeys.nextElement(); + + ObjectClassDefinitionImpl ocd = _dp_OCDs.get(dh._ocdref); + if (ocd != null) { + designates.add(new Designate.Builder(ocd).bundle(dh._bundle_val).factoryPid(dh._factory_val).merge(dh._merge_val).pid(dh._pid_val).optional(dh._optional_val).build()); + } else { + logger.log(LogService.LOG_ERROR, "DataParser.finished() " + NLS.bind(MetaTypeMsg.OCD_ID_NOT_FOUND, dh._ocdref)); //$NON-NLS-1$ + + } + } + } + } + + /** + * Handler for the ObjectClassDefinition element. + */ + private class OcdHandler extends AbstractHandler { + + Hashtable _parent_OCDs_hashtable; + // This ID "_refID" is only used for reference by Designate element, + // not the PID or FPID of this OCD. + String _refID; + ObjectClassDefinitionImpl _ocd; + Vector _ad_vector = new Vector(7); + + public OcdHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts, Hashtable ocds_hashtable) { + + logger.log(LogService.LOG_DEBUG, "Here is OcdHandler():init()"); //$NON-NLS-1$ + _parent_OCDs_hashtable = ocds_hashtable; + collectExtensionAttributes(atts); + String ocd_name_val = atts.getValue(NAME); + if (ocd_name_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Hashtable) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, NAME, name)); //$NON-NLS-1$ + return; + } + + String ocd_description_val = atts.getValue(DESCRIPTION); + if (ocd_description_val == null) { + // Not a problem, because DESCRIPTION is an optional attribute. + } + + _refID = atts.getValue(ID); + if (_refID == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Hashtable) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, ID, name)); //$NON-NLS-1$ + return; + } + + _ocd = new ObjectClassDefinitionImpl(ocd_name_val, ocd_description_val, _refID, _dp_localization, extensionAttributes); + } + + public void startElement(String uri, String localName, String qName, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is OcdHandler:startElement():" //$NON-NLS-1$ + + qName); + if (!_isParsedDataValid) + return; + + String name = getName(localName, qName); + if (name.equalsIgnoreCase(AD)) { + AttributeDefinitionHandler attributeDefHandler = new AttributeDefinitionHandler(this); + attributeDefHandler.init(name, atts, _ad_vector); + } else if (name.equalsIgnoreCase(ICON)) { + IconHandler iconHandler = new IconHandler(this); + iconHandler.init(name, atts); + if (iconHandler._isParsedDataValid) { + // Because XML schema allows at most one icon for + // one OCD, if more than one icons are read from + // MetaData, then only the final icon will be kept. + _ocd.setIcon(iconHandler._icon); + } + } else { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); + } + } + + protected void finished() { + + logger.log(LogService.LOG_DEBUG, "Here is OcdHandler():finished()"); //$NON-NLS-1$ + if (!_isParsedDataValid) + return; + + if (_ad_vector.size() == 0) { + // Schema defines at least one AD is required. + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.finished() " + NLS.bind(MetaTypeMsg.MISSING_ELEMENT, AD, _refID)); //$NON-NLS-1$ + return; + } + // OCD gets all parsed ADs. + Enumeration adKey = _ad_vector.elements(); + while (adKey.hasMoreElements()) { + AttributeDefinitionImpl ad = adKey.nextElement(); + _ocd.addAttributeDefinition(ad, ad._isRequired); + } + + _parent_OCDs_hashtable.put(_refID, _ocd); + } + } + + /** + * Handler for the Icon element. + */ + private class IconHandler extends AbstractHandler { + + Icon _icon; + + public IconHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is IconHandler:init()"); //$NON-NLS-1$ + String icon_resource_val = atts.getValue(RESOURCE); + if (icon_resource_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, RESOURCE, name)); //$NON-NLS-1$ + return; + } + + String icon_size_val = atts.getValue(SIZE); + if (icon_size_val == null) { + // Not a problem, because SIZE is an optional attribute. + icon_size_val = "0"; //$NON-NLS-1$ + } else if (icon_size_val.equalsIgnoreCase("")) { //$NON-NLS-1$ + icon_size_val = "0"; //$NON-NLS-1$ + } + + _icon = new Icon(icon_resource_val, Integer.parseInt(icon_size_val), _dp_bundle); + } + } + + /** + * Handler for the Attribute element. + */ + private class AttributeDefinitionHandler extends AbstractHandler { + + AttributeDefinitionImpl _ad; + int _dataType; + + Vector _parent_ADs_vector; + Vector _optionLabel_vector = new Vector(7); + Vector _optionValue_vector = new Vector(7); + + public AttributeDefinitionHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts, Vector ad_vector) { + + logger.log(LogService.LOG_DEBUG, "Here is AttributeDefinitionHandler():init()"); //$NON-NLS-1$ + _parent_ADs_vector = ad_vector; + collectExtensionAttributes(atts); + String ad_name_val = atts.getValue(NAME); + if (ad_name_val == null) { + // Not a problem, because NAME is an optional attribute. + } + + String ad_description_val = atts.getValue(DESCRIPTION); + if (ad_description_val == null) { + // Not a problem, because DESCRIPTION is an optional attribute. + } + + String ad_id_val = atts.getValue(ID); + if (ad_id_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Vector) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, ID, name)); //$NON-NLS-1$ + return; + } + + String ad_type_val = atts.getValue(TYPE); + if (ad_type_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Vector) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, TYPE, name)); //$NON-NLS-1$ + return; + } + if (ad_type_val.equalsIgnoreCase(STRING)) { + _dataType = AttributeDefinition.STRING; + } else if (ad_type_val.equalsIgnoreCase(LONG)) { + _dataType = AttributeDefinition.LONG; + } else if (ad_type_val.equalsIgnoreCase(DOUBLE)) { + _dataType = AttributeDefinition.DOUBLE; + } else if (ad_type_val.equalsIgnoreCase(FLOAT)) { + _dataType = AttributeDefinition.FLOAT; + } else if (ad_type_val.equalsIgnoreCase(INTEGER)) { + _dataType = AttributeDefinition.INTEGER; + } else if (ad_type_val.equalsIgnoreCase(BYTE)) { + _dataType = AttributeDefinition.BYTE; + } else if (ad_type_val.equalsIgnoreCase(CHAR)) { + _dataType = AttributeDefinition.CHARACTER; + } else if (ad_type_val.equalsIgnoreCase(BOOLEAN)) { + _dataType = AttributeDefinition.BOOLEAN; + } else if (ad_type_val.equalsIgnoreCase(SHORT)) { + _dataType = AttributeDefinition.SHORT; + } else if (ad_type_val.equalsIgnoreCase(PASSWORD)) { + _dataType = AttributeDefinition.PASSWORD; + } else { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes, Vector) " + NLS.bind(MetaTypeMsg.INVALID_TYPE, new Object[] {ad_type_val, _dp_url, _dp_bundle.getBundleId()})); //$NON-NLS-1$ + return; + } + + String ad_cardinality_str = atts.getValue(CARDINALITY); + int ad_cardinality_val = 0; + if (ad_cardinality_str == null) { + // Not a problem, because CARDINALITY is an optional attribute. + // And the default value is 0. + } else { + ad_cardinality_val = Integer.parseInt(ad_cardinality_str); + } + + String ad_min_val = atts.getValue(MIN); + if (ad_min_val == null) { + // Not a problem, because MIN is an optional attribute. + } + + String ad_max_val = atts.getValue(MAX); + if (ad_max_val == null) { + // Not a problem, because MAX is an optional attribute. + } + + String ad_defaults_str = atts.getValue(DEFAULT); + if (ad_defaults_str == null) { + // Not a problem, because DEFAULT is an optional attribute. + } + + String ad_required_val = atts.getValue(REQUIRED); + if (ad_required_val == null) { + // Not a problem, because REQUIRED is an optional attribute. + // And the default value is 'true'. + ad_required_val = Boolean.TRUE.toString(); + } + + _ad = new AttributeDefinitionImpl(ad_id_val, ad_name_val, ad_description_val, _dataType, ad_cardinality_val, convert(ad_min_val, _dataType), convert(ad_max_val, _dataType), Boolean.valueOf(ad_required_val).booleanValue(), _dp_localization, logger, extensionAttributes); + + if (ad_defaults_str != null) { + _ad.setDefaultValue(ad_defaults_str, true); + } + } + + public void startElement(String uri, String localName, String qName, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is AttributeDefinitionHandler:startElement():" //$NON-NLS-1$ + + qName); + if (!_isParsedDataValid) + return; + + String name = getName(localName, qName); + if (name.equalsIgnoreCase(OPTION)) { + OptionHandler optionHandler = new OptionHandler(this); + optionHandler.init(name, atts); + if (optionHandler._isParsedDataValid) { + // Only add valid Option + _optionLabel_vector.addElement(optionHandler._label_val); + _optionValue_vector.addElement(optionHandler._value_val); + } + } else { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); + } + } + + protected void finished() { + + logger.log(LogService.LOG_DEBUG, "Here is AttributeDefinitionHandler():finished()"); //$NON-NLS-1$ + if (!_isParsedDataValid) + return; + + _ad.setOption(_optionLabel_vector, _optionValue_vector, true); + _parent_ADs_vector.addElement(_ad); + } + } + + /** + * Handler for the Option element. + */ + private class OptionHandler extends AbstractHandler { + + String _label_val; + String _value_val; + + public OptionHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is OptionHandler:init()"); //$NON-NLS-1$ + _label_val = atts.getValue(LABEL); + if (_label_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, LABEL, name)); //$NON-NLS-1$ + return; + } + + _value_val = atts.getValue(VALUE); + if (_value_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, VALUE, name)); //$NON-NLS-1$ + return; + } + } + } + + // /** + // * Handler for the Simple Value element. + // */ + // private class SimpleValueHandler extends AbstractHandler { + // + // StringBuffer _buffer = new StringBuffer(); + // Vector _parent_value_vector; + // String _elementName; + // + // public SimpleValueHandler(ContentHandler handler) { + // super(handler); + // } + // + // public void init(String name, Attributes atts, Vector value_vector) + // throws SAXException { + // + // Logging.log(LogService.LOG_DEBUG, + // "Here is SimpleValueHandler():init()"); //$NON-NLS-1$ + // _elementName = name; + // _parent_value_vector = value_vector; + // } + // + // protected void finished() throws SAXException { + // + // Logging.log(LogService.LOG_DEBUG, + // "Here is SimpleValueHandler():finished()"); //$NON-NLS-1$ + // if (_parent_value_vector != null) { + // _parent_value_vector.addElement(_buffer.toString()); + // } + // } + // + // public void characters(char buf[], int offset, int len) + // throws SAXException { + // + // Logging.log(LogService.LOG_DEBUG, + // "Here is SimpleValueHandler(" //$NON-NLS-1$ + // + _elementName + // + "):characters():[" //$NON-NLS-1$ + // + new String(buf, offset, len) + // + "]"); //$NON-NLS-1$ + // _buffer.append(new String(buf, offset, len)); + // } + // } + + /** + * Handler for the Designate element. + */ + class DesignateHandler extends AbstractHandler { + + String _pid_val = null; + String _factory_val = null; + String _bundle_val = null; // Only used by RFC94 + boolean _optional_val = false; // Only used by RFC94 + boolean _merge_val = false; // Only used by RFC94 + + // Referenced OCD ID + String _ocdref; + + public DesignateHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is DesignateHandler():init()"); //$NON-NLS-1$ + _pid_val = atts.getValue(PID); + _factory_val = atts.getValue(FACTORY); + if (_pid_val == null && _factory_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, MetaTypeMsg.MISSING_DESIGNATE_PID_AND_FACTORYPID); + return; + } + + _bundle_val = atts.getValue(BUNDLE); + if (_bundle_val == null) { + // Not a problem because BUNDLE is an optional attribute. + } + + String optional_str = atts.getValue(OPTIONAL); + if (optional_str == null) { + // Not a problem, because OPTIONAL is an optional attribute. + // The default value is "false". + _optional_val = false; + } else { + _optional_val = Boolean.valueOf(optional_str).booleanValue(); + } + + String merge_str = atts.getValue(MERGE); + if (merge_str == null) { + // Not a problem, because MERGE is an optional attribute. + // The default value is "false". + _merge_val = false; + } else { + _merge_val = Boolean.valueOf(merge_str).booleanValue(); + } + } + + public void startElement(String uri, String localName, String qName, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is DesignateHandler:startElement():" //$NON-NLS-1$ + + qName); + if (!_isParsedDataValid) + return; + + String name = getName(localName, qName); + if (name.equalsIgnoreCase(OBJECT)) { + ObjectHandler objectHandler = new ObjectHandler(this); + objectHandler.init(name, atts); + if (objectHandler._isParsedDataValid) { + _ocdref = objectHandler._ocdref; + } + } else { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); + } + } + + protected void finished() { + + logger.log(LogService.LOG_DEBUG, "Here is DesignateHandler():finished()"); //$NON-NLS-1$ + if (!_isParsedDataValid) + return; + + if (_ocdref == null) { + _isParsedDataValid = false; + // Schema defines at least one OBJECT is required. + logger.log(LogService.LOG_ERROR, "DataParser.finished() " + NLS.bind(MetaTypeMsg.MISSING_ELEMENT, OBJECT, _pid_val)); //$NON-NLS-1$ + return; + + } + } + } + + /** + * Handler for the Object element. + */ + private class ObjectHandler extends AbstractHandler { + + String _ocdref; + + public ObjectHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is ObjectHandler():init()"); //$NON-NLS-1$ + _ocdref = atts.getValue(OCDREF); + if (_ocdref == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, OCDREF, name)); //$NON-NLS-1$ + return; + } + } + + public void startElement(String uri, String localName, String qName, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is ObjectHandler:startElement():" //$NON-NLS-1$ + + qName); + if (!_isParsedDataValid) + return; + + String name = getName(localName, qName); + if (name.equalsIgnoreCase(ATTRIBUTE)) { + AttributeHandler attributeHandler = new AttributeHandler(this); + attributeHandler.init(name, atts); + // The ATTRIBUTE element is only used by RFC94, do nothing for it here. + } else { + logger.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.UNEXPECTED_ELEMENT, name)); + } + } + } + + /** + * Handler for the Attribute element. + * + * This Handler is only used by RFC94. + */ + private class AttributeHandler extends AbstractHandler { + + String _adref_val; + String _content_val; + + public AttributeHandler(ContentHandler handler) { + super(handler); + } + + public void init(String name, Attributes atts) { + + logger.log(LogService.LOG_DEBUG, "Here is AttributeHandler():init()"); //$NON-NLS-1$ + _adref_val = atts.getValue(ADREF); + if (_adref_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, ADREF, name)); //$NON-NLS-1$ + return; + } + + _content_val = atts.getValue(CONTENT); + if (_content_val == null) { + _isParsedDataValid = false; + logger.log(LogService.LOG_ERROR, "DataParser.init(String, Attributes) " + NLS.bind(MetaTypeMsg.MISSING_ATTRIBUTE, CONTENT, name)); //$NON-NLS-1$ + return; + } + } + } + + /** + * Error Handler to report errors and warnings + */ + private static class MyErrorHandler implements ErrorHandler { + + /** Error handler output goes here */ + private PrintStream _out; + + MyErrorHandler(PrintStream out) { + this._out = out; + } + + /** + * Returns a string describing parse exception details + */ + private String getParseExceptionInfo(SAXParseException spe) { + String systemId = spe.getSystemId(); + if (systemId == null) { + systemId = "null"; //$NON-NLS-1$ + } + String info = "URI=" + systemId + //$NON-NLS-1$ + " Line=" + spe.getLineNumber() + //$NON-NLS-1$ + ": " + spe.getMessage(); //$NON-NLS-1$ + + return info; + } + + // The following methods are standard SAX ErrorHandler methods. + // See SAX documentation for more info. + + public void warning(SAXParseException spe) { + _out.println("Warning: " + getParseExceptionInfo(spe)); //$NON-NLS-1$ + } + + public void error(SAXParseException spe) throws SAXException { + String message = "Error: " + getParseExceptionInfo(spe); //$NON-NLS-1$ + throw new SAXException(message); + } + + public void fatalError(SAXParseException spe) throws SAXException { + String message = "Fatal Error: " + getParseExceptionInfo(spe); //$NON-NLS-1$ + throw new SAXException(message); + } + } + + public static String getName(String localName, String qName) { + if (localName != null && localName.length() > 0) { + return localName; + } + + int nameSpaceIndex = qName.indexOf(":"); //$NON-NLS-1$ + return nameSpaceIndex == -1 ? qName : qName.substring(nameSpaceIndex + 1); + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Designate.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Designate.java index 83b31b1a8..f15e9457d 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Designate.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Designate.java @@ -1,104 +1,104 @@ -/******************************************************************************* - * Copyright (c) 2011 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.metatype.impl; - -import org.eclipse.osgi.util.NLS; - -public class Designate { - public static class Builder { - String bundle; - String factoryPid; - boolean merge; - ObjectClassDefinitionImpl ocd; - boolean optional; - String pid; - - public Builder(ObjectClassDefinitionImpl ocd) { - if (ocd == null) { - throw new IllegalArgumentException(NLS.bind(MetaTypeMsg.MISSING_REQUIRED_PARAMETER, "ocd")); //$NON-NLS-1$ - } - this.ocd = ocd; - } - - public Designate build() { - return new Designate(this); - } - - public Builder bundle(String value) { - bundle = value; - return this; - } - - public Builder factoryPid(String value) { - factoryPid = value; - return this; - } - - public Builder merge(boolean value) { - merge = value; - return this; - } - - public Builder optional(boolean value) { - optional = value; - return this; - } - - public Builder pid(String value) { - pid = value; - return this; - } - } - - private final String bundle; - private final String factoryPid; - private final boolean merge; - private final ObjectClassDefinitionImpl ocd; - private final boolean optional; - private final String pid; - - Designate(Builder b) { - bundle = b.bundle; - factoryPid = b.factoryPid; - merge = b.merge; - ocd = b.ocd; - optional = b.optional; - pid = b.pid; - } - - public String getBundle() { - return bundle; - } - - public String getFactoryPid() { - return factoryPid; - } - - public boolean isFactory() { - return factoryPid != null && factoryPid.length() != 0; - } - - public boolean isMerge() { - return merge; - } - - public ObjectClassDefinitionImpl getObjectClassDefinition() { - return ocd; - } - - public boolean isOptional() { - return optional; - } - - public String getPid() { - return pid; - } -} +/******************************************************************************* + * Copyright (c) 2011 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.metatype.impl; + +import org.eclipse.osgi.util.NLS; + +public class Designate { + public static class Builder { + String bundle; + String factoryPid; + boolean merge; + ObjectClassDefinitionImpl ocd; + boolean optional; + String pid; + + public Builder(ObjectClassDefinitionImpl ocd) { + if (ocd == null) { + throw new IllegalArgumentException(NLS.bind(MetaTypeMsg.MISSING_REQUIRED_PARAMETER, "ocd")); //$NON-NLS-1$ + } + this.ocd = ocd; + } + + public Designate build() { + return new Designate(this); + } + + public Builder bundle(String value) { + bundle = value; + return this; + } + + public Builder factoryPid(String value) { + factoryPid = value; + return this; + } + + public Builder merge(boolean value) { + merge = value; + return this; + } + + public Builder optional(boolean value) { + optional = value; + return this; + } + + public Builder pid(String value) { + pid = value; + return this; + } + } + + private final String bundle; + private final String factoryPid; + private final boolean merge; + private final ObjectClassDefinitionImpl ocd; + private final boolean optional; + private final String pid; + + Designate(Builder b) { + bundle = b.bundle; + factoryPid = b.factoryPid; + merge = b.merge; + ocd = b.ocd; + optional = b.optional; + pid = b.pid; + } + + public String getBundle() { + return bundle; + } + + public String getFactoryPid() { + return factoryPid; + } + + public boolean isFactory() { + return factoryPid != null && factoryPid.length() != 0; + } + + public boolean isMerge() { + return merge; + } + + public ObjectClassDefinitionImpl getObjectClassDefinition() { + return ocd; + } + + public boolean isOptional() { + return optional; + } + + public String getPid() { + return pid; + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExtendableHelper.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExtendableHelper.java index c48b75374..0bccad9a5 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExtendableHelper.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExtendableHelper.java @@ -1,39 +1,39 @@ -/******************************************************************************* - * Copyright (c) 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.Extendable; - -import java.util.*; - -public class ExtendableHelper implements Extendable { - private final Map> attributes; - - @SuppressWarnings("unchecked") - public ExtendableHelper() { - this(Collections.EMPTY_MAP); - } - - public ExtendableHelper(Map> attributes) { - if (attributes == null) - throw new NullPointerException(); - this.attributes = attributes; - } - - public Map getExtensionAttributes(String schema) { - return Collections.unmodifiableMap(attributes.get(schema)); - } - - public Set getExtensionUris() { - return Collections.unmodifiableSet(attributes.keySet()); - } - -} +/******************************************************************************* + * Copyright (c) 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.Extendable; + +import java.util.*; + +public class ExtendableHelper implements Extendable { + private final Map> attributes; + + @SuppressWarnings("unchecked") + public ExtendableHelper() { + this(Collections.EMPTY_MAP); + } + + public ExtendableHelper(Map> attributes) { + if (attributes == null) + throw new NullPointerException(); + this.attributes = attributes; + } + + public Map getExtensionAttributes(String schema) { + return Collections.unmodifiableMap(attributes.get(schema)); + } + + public Set getExtensionUris() { + return Collections.unmodifiableSet(attributes.keySet()); + } + +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExternalMessages.properties b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExternalMessages.properties index ff60175e8..820963ad5 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExternalMessages.properties +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ExternalMessages.properties @@ -1,37 +1,37 @@ -############################################################################### -# Copyright (c) 2005, 2011 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 -############################################################################### -#External Messages for EN locale -SERVICE_DESCRIPTION=OSGi Metatype Service - IBM Implementation - -UNEXPECTED_ELEMENT=Unexpected element {0}. -UNEXPECTED_TEXT=Unexpected text {0}. -MISSING_ATTRIBUTE=Missing attribute {0} in tag {1}. -INVALID_TYPE=Invalid attribute definition type {0} in metadata XML at {1} for bundle ID {2}. -MISSING_DESIGNATE_PID_AND_FACTORYPID=A element must specify either the 'pid' or 'factoryPid' attribute. -OCD_ID_NOT_FOUND=Object Class Definition ID not found {0}. -MISSING_ELEMENT=Missing element {0} (Reference ID = {1}. - -EXCEPTION_MESSAGE=Unexpected exception {0} with message {1}. -NULL_IS_INVALID=Cannot validate a null. -VALUE_OUT_OF_RANGE=Value {0} is out of range. -VALUE_OUT_OF_OPTION=Value {0} is out of Option. -CARDINALITY_VIOLATION=Cardinality violation: \"{0}\" has {1} value(s) but must have between {2} and {3} value(s). -NULL_OPTIONS=Cannot set Option labels or values as null. -INCONSISTENT_OPTIONS=Labels and Values of Option have different sizes. -INVALID_OPTIONS=Option value {0} is invalid because of {1}. -INVALID_DEFAULTS=Dafaults value {0} is invalid because of {1}. - -METADATA_NOT_FOUND=Bundle(ID=\"{0}\", name=\"{1}\") has no MetaData file. -ASK_INVALID_LOCALE=OCD(ID=\"{0}\") cannot support this locale \"{1}\". -MISSING_REQUIRED_PARAMETER=Missing required parameter: {0} -TOKENIZER_GOT_INVALID_DATA=The Tokenizer got invalid data. -INVALID_PID_METATYPE_PROVIDER_IGNORED=Bundle {0} with ID {1} provided a MetaTypeProvider with an invalid property. Property {2} with value {3} was not of the expected type (String, String[], or Collection) and will be ignored. +############################################################################### +# Copyright (c) 2005, 2011 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 +############################################################################### +#External Messages for EN locale +SERVICE_DESCRIPTION=OSGi Metatype Service - IBM Implementation + +UNEXPECTED_ELEMENT=Unexpected element {0}. +UNEXPECTED_TEXT=Unexpected text {0}. +MISSING_ATTRIBUTE=Missing attribute {0} in tag {1}. +INVALID_TYPE=Invalid attribute definition type {0} in metadata XML at {1} for bundle ID {2}. +MISSING_DESIGNATE_PID_AND_FACTORYPID=A element must specify either the 'pid' or 'factoryPid' attribute. +OCD_ID_NOT_FOUND=Object Class Definition ID not found {0}. +MISSING_ELEMENT=Missing element {0} (Reference ID = {1}. + +EXCEPTION_MESSAGE=Unexpected exception {0} with message {1}. +NULL_IS_INVALID=Cannot validate a null. +VALUE_OUT_OF_RANGE=Value {0} is out of range. +VALUE_OUT_OF_OPTION=Value {0} is out of Option. +CARDINALITY_VIOLATION=Cardinality violation: \"{0}\" has {1} value(s) but must have between {2} and {3} value(s). +NULL_OPTIONS=Cannot set Option labels or values as null. +INCONSISTENT_OPTIONS=Labels and Values of Option have different sizes. +INVALID_OPTIONS=Option value {0} is invalid because of {1}. +INVALID_DEFAULTS=Dafaults value {0} is invalid because of {1}. + +METADATA_NOT_FOUND=Bundle(ID=\"{0}\", name=\"{1}\") has no MetaData file. +ASK_INVALID_LOCALE=OCD(ID=\"{0}\") cannot support this locale \"{1}\". +MISSING_REQUIRED_PARAMETER=Missing required parameter: {0} +TOKENIZER_GOT_INVALID_DATA=The Tokenizer got invalid data. +INVALID_PID_METATYPE_PROVIDER_IGNORED=Bundle {0} with ID {1} provided a MetaTypeProvider with an invalid property. Property {2} with value {3} was not of the expected type (String, String[], or Collection) and will be ignored. METADATA_PARSE_ERROR=Unable to parse metadata XML at {0} for bundle ID {1}. \ No newline at end of file diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/FragmentUtils.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/FragmentUtils.java index 0685e1509..e455ae641 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/FragmentUtils.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/FragmentUtils.java @@ -1,58 +1,58 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import java.net.URL; -import java.util.List; -import org.osgi.framework.Bundle; -import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.BundleWiring; - -/* - * Fragment Utilities - */ -public class FragmentUtils { - - /* - * - */ - public static boolean isFragment(Bundle bundle) { - return (bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0; - } - - /* - * Find all the URLs to entries for the bundle and its fragments. - */ - public static URL[] findEntries(Bundle bundle, String path) { - BundleWiring wiring = bundle.adapt(BundleWiring.class); - if (wiring == null) - return null; - String directory = "/"; //$NON-NLS-1$ - String file = "*"; //$NON-NLS-1$ - int index = path.lastIndexOf(MetaTypeProviderImpl.DIRECTORY_SEP); - switch (index) { - case -1 : - file = path; - break; - case 0 : - if (path.length() > 1) - file = path.substring(1); - break; - default : - directory = path.substring(0, index); - file = path.substring(index + 1); - } - List entries = wiring.findEntries(directory, file, 0); - if (entries == null) - return null; - return entries.toArray(new URL[entries.size()]); - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import java.net.URL; +import java.util.List; +import org.osgi.framework.Bundle; +import org.osgi.framework.wiring.BundleRevision; +import org.osgi.framework.wiring.BundleWiring; + +/* + * Fragment Utilities + */ +public class FragmentUtils { + + /* + * + */ + public static boolean isFragment(Bundle bundle) { + return (bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0; + } + + /* + * Find all the URLs to entries for the bundle and its fragments. + */ + public static URL[] findEntries(Bundle bundle, String path) { + BundleWiring wiring = bundle.adapt(BundleWiring.class); + if (wiring == null) + return null; + String directory = "/"; //$NON-NLS-1$ + String file = "*"; //$NON-NLS-1$ + int index = path.lastIndexOf(MetaTypeProviderImpl.DIRECTORY_SEP); + switch (index) { + case -1 : + file = path; + break; + case 0 : + if (path.length() > 1) + file = path.substring(1); + break; + default : + directory = path.substring(0, index); + file = path.substring(index + 1); + } + List entries = wiring.findEntries(directory, file, 0); + if (entries == null) + return null; + return entries.toArray(new URL[entries.size()]); + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Icon.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Icon.java index 161309721..591914e94 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Icon.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/Icon.java @@ -1,72 +1,72 @@ -/******************************************************************************* - * Copyright (c) 2005 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.metatype.impl; - -import org.osgi.framework.Bundle; - -/** - * Represents an Icon with a name and a size - */ -class Icon implements Cloneable { - - private String _fileName; - private int _size; - private Bundle _bundle; - - /** - * Constructor of class Icon. - */ - public Icon(String fileName, int size, Bundle bundle) { - - this._fileName = fileName; - this._size = size; - this._bundle = bundle; - } - - /** - * Constructor of class Icon. - */ - public Icon(String fileName, Bundle bundle) { - - // Integer.MIN_VALUE signifies size was not specified - this(fileName, Integer.MIN_VALUE, bundle); - } - - /* - * - */ - public synchronized Object clone() { - return new Icon(this._fileName, this._size, this._bundle); - } - - /** - * Method to get the icon's file name. - */ - String getIconName() { - return _fileName; - } - - /** - * returns the size specified when the icon was created - * - * @return size or Integer.MIN_VALUE if no size was specified - */ - int getIconSize() { - return _size; - } - - /** - * Method to get the bundle having this Icon. - */ - Bundle getIconBundle() { - return _bundle; - } -} +/******************************************************************************* + * Copyright (c) 2005 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.metatype.impl; + +import org.osgi.framework.Bundle; + +/** + * Represents an Icon with a name and a size + */ +class Icon implements Cloneable { + + private String _fileName; + private int _size; + private Bundle _bundle; + + /** + * Constructor of class Icon. + */ + public Icon(String fileName, int size, Bundle bundle) { + + this._fileName = fileName; + this._size = size; + this._bundle = bundle; + } + + /** + * Constructor of class Icon. + */ + public Icon(String fileName, Bundle bundle) { + + // Integer.MIN_VALUE signifies size was not specified + this(fileName, Integer.MIN_VALUE, bundle); + } + + /* + * + */ + public synchronized Object clone() { + return new Icon(this._fileName, this._size, this._bundle); + } + + /** + * Method to get the icon's file name. + */ + String getIconName() { + return _fileName; + } + + /** + * returns the size specified when the icon was created + * + * @return size or Integer.MIN_VALUE if no size was specified + */ + int getIconSize() { + return _size; + } + + /** + * Method to get the bundle having this Icon. + */ + Bundle getIconBundle() { + return _bundle; + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LocalizationElement.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LocalizationElement.java index fbb0ebce3..46dce3155 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LocalizationElement.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LocalizationElement.java @@ -1,55 +1,55 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import java.util.MissingResourceException; -import java.util.ResourceBundle; - -public class LocalizationElement { - - public static final char KEY_SIGN = '%'; - String _localization = null; - ResourceBundle _rb; - - /** - * Internal method - */ - void setResourceBundle(ResourceBundle rb) { - this._rb = rb; - } - - /** - * Method to get the localized text of inputed String. - */ - String getLocalized(String key) { - - if (key == null) { - return null; - } - - if ((key.length() > 1) && (key.charAt(0) == KEY_SIGN)) { - if (_rb != null) { - try { - String transfered = _rb.getString(key.substring(1)); - if (transfered != null) { - return transfered; - } - } catch (MissingResourceException mre) { - // Nothing found for this key. - } - } - // If no localization file available or no localized value found - // for the key, then return the raw data without the key-sign. - return key.substring(1); - } - return key; - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class LocalizationElement { + + public static final char KEY_SIGN = '%'; + String _localization = null; + ResourceBundle _rb; + + /** + * Internal method + */ + void setResourceBundle(ResourceBundle rb) { + this._rb = rb; + } + + /** + * Method to get the localized text of inputed String. + */ + String getLocalized(String key) { + + if (key == null) { + return null; + } + + if ((key.length() > 1) && (key.charAt(0) == KEY_SIGN)) { + if (_rb != null) { + try { + String transfered = _rb.getString(key.substring(1)); + if (transfered != null) { + return transfered; + } + } catch (MissingResourceException mre) { + // Nothing found for this key. + } + } + // If no localization file available or no localized value found + // for the key, then return the raw data without the key-sign. + return key.substring(1); + } + return key; + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogMessages.properties b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogMessages.properties index 6ac12381c..cf8d9a411 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogMessages.properties +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogMessages.properties @@ -1,17 +1,17 @@ -############################################################################### -# Copyright (c) 2005, 2010 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 -############################################################################### -# NLS_MESSAGEFORMAT_ALL - -Unknown_Log_level=Unknown Log Level -Info=Log Info -Warning=Log Warning -Error=Log Error -Debug=Log Debug +############################################################################### +# Copyright (c) 2005, 2010 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 +############################################################################### +# NLS_MESSAGEFORMAT_ALL + +Unknown_Log_level=Unknown Log Level +Info=Log Info +Warning=Log Warning +Error=Log Error +Debug=Log Debug diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTracker.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTracker.java index 51e58c9db..3f4fc71dc 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTracker.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTracker.java @@ -1,177 +1,177 @@ -/******************************************************************************* - * Copyright (c) 1998, 2010 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.metatype.impl; - -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); - } - - // Must suppress warnings here because the log service is not - @SuppressWarnings("rawtypes") - public void log(ServiceReference reference, int level, String message) { - log(reference, level, message, null); - } - - // Must suppress warnings here because the log service is not - @SuppressWarnings("rawtypes") - 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 = 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(LogTrackerMsg.Debug); - - break; - } - case LOG_INFO : { - out.print(LogTrackerMsg.Info); - - break; - } - case LOG_WARNING : { - out.print(LogTrackerMsg.Warning); - - break; - } - case LOG_ERROR : { - out.print(LogTrackerMsg.Error); - - break; - } - default : { - out.print("["); //$NON-NLS-1$ - out.print(LogTrackerMsg.Unknown_Log_level); - out.print("]: "); //$NON-NLS-1$ - - break; - } - } - - 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; - } -} +/******************************************************************************* + * Copyright (c) 1998, 2010 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.metatype.impl; + +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); + } + + // Must suppress warnings here because the log service is not + @SuppressWarnings("rawtypes") + public void log(ServiceReference reference, int level, String message) { + log(reference, level, message, null); + } + + // Must suppress warnings here because the log service is not + @SuppressWarnings("rawtypes") + 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 = 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(LogTrackerMsg.Debug); + + break; + } + case LOG_INFO : { + out.print(LogTrackerMsg.Info); + + break; + } + case LOG_WARNING : { + out.print(LogTrackerMsg.Warning); + + break; + } + case LOG_ERROR : { + out.print(LogTrackerMsg.Error); + + break; + } + default : { + out.print("["); //$NON-NLS-1$ + out.print(LogTrackerMsg.Unknown_Log_level); + out.print("]: "); //$NON-NLS-1$ + + break; + } + } + + 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; + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTrackerMsg.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTrackerMsg.java index 06cdaab34..3a30ef14b 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTrackerMsg.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/LogTrackerMsg.java @@ -1,28 +1,28 @@ -/******************************************************************************* - * Copyright (c) 2005, 2010 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.metatype.impl; - -import org.eclipse.osgi.util.NLS; - -public class LogTrackerMsg extends NLS { - private static final String BUNDLE_NAME = "org.eclipse.equinox.metatype.impl.LogMessages"; //$NON-NLS-1$ - - public static String Unknown_Log_level; - public static String Info; - public static String Warning; - public static String Error; - public static String Debug; - - static { - // initialize resource bundles - NLS.initializeMessages(BUNDLE_NAME, LogTrackerMsg.class); - } -} +/******************************************************************************* + * Copyright (c) 2005, 2010 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.metatype.impl; + +import org.eclipse.osgi.util.NLS; + +public class LogTrackerMsg extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.equinox.metatype.impl.LogMessages"; //$NON-NLS-1$ + + public static String Unknown_Log_level; + public static String Info; + public static String Warning; + public static String Error; + public static String Debug; + + static { + // initialize resource bundles + NLS.initializeMessages(BUNDLE_NAME, LogTrackerMsg.class); + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeInformationImpl.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeInformationImpl.java index 11e823871..a9780ff68 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeInformationImpl.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeInformationImpl.java @@ -1,89 +1,89 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.EquinoxMetaTypeInformation; - -import java.util.Enumeration; -import java.util.Vector; -import javax.xml.parsers.SAXParser; -import org.osgi.framework.Bundle; -import org.osgi.service.log.LogService; - -/** - * Implementation of MetaTypeProvider - *

- * Extension of MetaTypeProvider - *

- * Provides methods to: - *

- getPids() get the Pids for a given Locale - *

- getFactoryPids() get the Factory Pids for a given Locale - *

- */ -public class MetaTypeInformationImpl extends MetaTypeProviderImpl implements EquinoxMetaTypeInformation { - - /** - * Constructor of class MetaTypeInformationImpl. - */ - MetaTypeInformationImpl(Bundle bundle, SAXParser parser, LogService logger) { - super(bundle, parser, logger); - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.MetaTypeInformation#getPids() - */ - public String[] getPids() { - - if (_allPidOCDs.size() == 0) { - return new String[0]; - } - - Vector pids = new Vector(7); - Enumeration e = _allPidOCDs.keys(); - while (e.hasMoreElements()) { - pids.addElement(e.nextElement()); - } - - String[] retvalue = new String[pids.size()]; - pids.toArray(retvalue); - return retvalue; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.MetaTypeInformation#getFactoryPids() - */ - public String[] getFactoryPids() { - if (_allFPidOCDs.size() == 0) { - return new String[0]; - } - Vector fpids = new Vector(7); - Enumeration e = _allFPidOCDs.keys(); - while (e.hasMoreElements()) { - fpids.addElement(e.nextElement()); - } - String[] retvalue = new String[fpids.size()]; - fpids.toArray(retvalue); - return retvalue; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.MetaTypeInformation#getBundle() - */ - public Bundle getBundle() { - return this._bundle; - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.EquinoxMetaTypeInformation; + +import java.util.Enumeration; +import java.util.Vector; +import javax.xml.parsers.SAXParser; +import org.osgi.framework.Bundle; +import org.osgi.service.log.LogService; + +/** + * Implementation of MetaTypeProvider + *

+ * Extension of MetaTypeProvider + *

+ * Provides methods to: + *

- getPids() get the Pids for a given Locale + *

- getFactoryPids() get the Factory Pids for a given Locale + *

+ */ +public class MetaTypeInformationImpl extends MetaTypeProviderImpl implements EquinoxMetaTypeInformation { + + /** + * Constructor of class MetaTypeInformationImpl. + */ + MetaTypeInformationImpl(Bundle bundle, SAXParser parser, LogService logger) { + super(bundle, parser, logger); + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeInformation#getPids() + */ + public String[] getPids() { + + if (_allPidOCDs.size() == 0) { + return new String[0]; + } + + Vector pids = new Vector(7); + Enumeration e = _allPidOCDs.keys(); + while (e.hasMoreElements()) { + pids.addElement(e.nextElement()); + } + + String[] retvalue = new String[pids.size()]; + pids.toArray(retvalue); + return retvalue; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeInformation#getFactoryPids() + */ + public String[] getFactoryPids() { + if (_allFPidOCDs.size() == 0) { + return new String[0]; + } + Vector fpids = new Vector(7); + Enumeration e = _allFPidOCDs.keys(); + while (e.hasMoreElements()) { + fpids.addElement(e.nextElement()); + } + String[] retvalue = new String[fpids.size()]; + fpids.toArray(retvalue); + return retvalue; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeInformation#getBundle() + */ + public Bundle getBundle() { + return this._bundle; + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeMsg.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeMsg.java index 6c7d4e9d8..b5fb57428 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeMsg.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeMsg.java @@ -1,46 +1,46 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.osgi.util.NLS; - -public class MetaTypeMsg extends NLS { - private static final String BUNDLE_NAME = "org.eclipse.equinox.metatype.impl.ExternalMessages"; //$NON-NLS-1$ - - public static String SERVICE_DESCRIPTION; - public static String UNEXPECTED_ELEMENT; - public static String UNEXPECTED_TEXT; - public static String MISSING_ATTRIBUTE; - public static String INVALID_TYPE; - public static String MISSING_DESIGNATE_PID_AND_FACTORYPID; - public static String OCD_ID_NOT_FOUND; - public static String MISSING_ELEMENT; - public static String EXCEPTION_MESSAGE; - public static String NULL_IS_INVALID; - public static String VALUE_OUT_OF_RANGE; - public static String VALUE_OUT_OF_OPTION; - public static String CARDINALITY_VIOLATION; - public static String NULL_OPTIONS; - public static String INCONSISTENT_OPTIONS; - public static String INVALID_OPTIONS; - public static String INVALID_DEFAULTS; - public static String METADATA_NOT_FOUND; - public static String ASK_INVALID_LOCALE; - public static String MISSING_REQUIRED_PARAMETER; - public static String TOKENIZER_GOT_INVALID_DATA; - public static String INVALID_PID_METATYPE_PROVIDER_IGNORED; - public static String METADATA_PARSE_ERROR; - - static { - // initialize resource bundles - NLS.initializeMessages(BUNDLE_NAME, MetaTypeMsg.class); - } +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.osgi.util.NLS; + +public class MetaTypeMsg extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.equinox.metatype.impl.ExternalMessages"; //$NON-NLS-1$ + + public static String SERVICE_DESCRIPTION; + public static String UNEXPECTED_ELEMENT; + public static String UNEXPECTED_TEXT; + public static String MISSING_ATTRIBUTE; + public static String INVALID_TYPE; + public static String MISSING_DESIGNATE_PID_AND_FACTORYPID; + public static String OCD_ID_NOT_FOUND; + public static String MISSING_ELEMENT; + public static String EXCEPTION_MESSAGE; + public static String NULL_IS_INVALID; + public static String VALUE_OUT_OF_RANGE; + public static String VALUE_OUT_OF_OPTION; + public static String CARDINALITY_VIOLATION; + public static String NULL_OPTIONS; + public static String INCONSISTENT_OPTIONS; + public static String INVALID_OPTIONS; + public static String INVALID_DEFAULTS; + public static String METADATA_NOT_FOUND; + public static String ASK_INVALID_LOCALE; + public static String MISSING_REQUIRED_PARAMETER; + public static String TOKENIZER_GOT_INVALID_DATA; + public static String INVALID_PID_METATYPE_PROVIDER_IGNORED; + public static String METADATA_PARSE_ERROR; + + static { + // initialize resource bundles + NLS.initializeMessages(BUNDLE_NAME, MetaTypeMsg.class); + } } \ No newline at end of file diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderImpl.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderImpl.java index 9342689e7..66d518bf9 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderImpl.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderImpl.java @@ -1,239 +1,239 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.EquinoxObjectClassDefinition; - -import java.io.IOException; -import java.net.URL; -import java.util.*; -import javax.xml.parsers.SAXParser; -import org.eclipse.osgi.util.NLS; -import org.osgi.framework.Bundle; -import org.osgi.framework.Constants; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.service.log.LogService; -import org.osgi.service.metatype.MetaTypeProvider; -import org.osgi.service.metatype.MetaTypeService; - -/** - * Implementation of MetaTypeProvider - */ -public class MetaTypeProviderImpl implements MetaTypeProvider { - - public static final String METADATA_NOT_FOUND = "METADATA_NOT_FOUND"; //$NON-NLS-1$ - public static final String OCD_ID_NOT_FOUND = "OCD_ID_NOT_FOUND"; //$NON-NLS-1$ - public static final String ASK_INVALID_LOCALE = "ASK_INVALID_LOCALE"; //$NON-NLS-1$ - - public static final String META_FILE_EXT = ".XML"; //$NON-NLS-1$ - public static final String RESOURCE_FILE_CONN = "_"; //$NON-NLS-1$ - public static final String RESOURCE_FILE_EXT = ".properties"; //$NON-NLS-1$ - public static final char DIRECTORY_SEP = '/'; - - Bundle _bundle; - - Hashtable _allPidOCDs = new Hashtable(7); - Hashtable _allFPidOCDs = new Hashtable(7); - - String[] _locales; - boolean _isThereMeta = false; - - // Give access to subclasses. - protected final LogService logger; - - /** - * Constructor of class MetaTypeProviderImpl. - */ - MetaTypeProviderImpl(Bundle bundle, SAXParser parser, LogService logger) { - - this._bundle = bundle; - this.logger = logger; - - // read all bundle's metadata files and build internal data structures - _isThereMeta = readMetaFiles(bundle, parser); - - if (!_isThereMeta) { - logger.log(LogService.LOG_DEBUG, NLS.bind(MetaTypeMsg.METADATA_NOT_FOUND, new Long(bundle.getBundleId()), bundle.getSymbolicName())); - } - } - - /** - * This method should do the following: - *

- Obtain a SAX parser from the XML Parser Service: - *

- * - *

	
- * - * The parser may be SAX 1 (eXML) or SAX 2 (XML4J). It should attempt to use - * a SAX2 parser by instantiating an XMLReader and extending DefaultHandler - * BUT if that fails it should fall back to instantiating a SAX1 Parser and - * extending HandlerBase. - *

- Pass the parser the URL for the bundle's METADATA.XML file - *

- Handle the callbacks from the parser and build the appropriate - * MetaType objects - ObjectClassDefinitions & AttributeDefinitions - * - * @param bundle The bundle object for which the metadata should be read - * @param parserFactory The bundle object for which the metadata should be - * read - * @return void - * @throws IOException If there are errors accessing the metadata.xml file - */ - private boolean readMetaFiles(Bundle bundle, SAXParser saxParser) { - BundleWiring wiring = bundle.adapt(BundleWiring.class); - if (wiring == null) - return false; - List entries = wiring.findEntries(MetaTypeService.METATYPE_DOCUMENTS_LOCATION, "*", 0); //$NON-NLS-1$ - if (entries == null) - return false; - boolean result = false; - for (URL entry : entries) { - if (entry.getPath().endsWith("/")) //$NON-NLS-1$ - continue; - DataParser parser = new DataParser(bundle, entry, saxParser, logger); - try { - Collection designates = parser.doParse(); - if (!designates.isEmpty()) { - result = true; - } - for (Designate designate : designates) { - if (designate.isFactory()) { - _allFPidOCDs.put(designate.getFactoryPid(), designate.getObjectClassDefinition()); - } else { - _allPidOCDs.put(designate.getPid(), designate.getObjectClassDefinition()); - } - } - } catch (Exception e) { - logger.log(LogService.LOG_ERROR, NLS.bind(MetaTypeMsg.METADATA_PARSE_ERROR, new Object[] {entry, bundle.getBundleId()}), e); - } - } - return result; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.MetaTypeProvider#getObjectClassDefinition(java.lang.String, - * java.lang.String) - */ - public EquinoxObjectClassDefinition getObjectClassDefinition(String pid, String locale) { - - if (isInvalidLocale(locale)) { - throw new IllegalArgumentException(NLS.bind(MetaTypeMsg.ASK_INVALID_LOCALE, pid, locale)); - } - - ObjectClassDefinitionImpl ocd; - if (_allPidOCDs.containsKey(pid)) { - ocd = (ObjectClassDefinitionImpl) (_allPidOCDs.get(pid)).clone(); - ocd.setResourceBundle(locale, _bundle); - return ocd; - } else if (_allFPidOCDs.containsKey(pid)) { - ocd = (ObjectClassDefinitionImpl) (_allFPidOCDs.get(pid)).clone(); - ocd.setResourceBundle(locale, _bundle); - return ocd; - } else { - throw new IllegalArgumentException(NLS.bind(MetaTypeMsg.OCD_ID_NOT_FOUND, pid)); - } - } - - /** - * Internal Method - Check if the locale is invalid. - */ - public boolean isInvalidLocale(String locale) { - - // Just a simple and quick check here. - if (locale == null || locale.length() == 0) - return false; - - int idx_first = locale.indexOf(ObjectClassDefinitionImpl.LOCALE_SEP); - int idx_second = locale.lastIndexOf(ObjectClassDefinitionImpl.LOCALE_SEP); - if (idx_first == -1 && locale.length() == 2) - // It is format of only language. - return false; - if ((idx_first == 2) && (idx_second == 5 || idx_second == 2)) - // It is format of language + "_" + country [ + "_" + variation ]. - return false; - return true; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.MetaTypeProvider#getLocales() - */ - public synchronized String[] getLocales() { - - if (_locales != null) - return checkForDefault(_locales); - BundleWiring wiring = _bundle.adapt(BundleWiring.class); - if (wiring == null) - return null; - Vector localizationFiles = new Vector(7); - // get all the localization resources for PIDS - Enumeration ocds = _allPidOCDs.elements(); - while (ocds.hasMoreElements()) { - ObjectClassDefinitionImpl ocd = ocds.nextElement(); - if (ocd._localization != null && !localizationFiles.contains(ocd._localization)) - localizationFiles.add(ocd._localization); - } - // get all the localization resources for FPIDS - ocds = _allFPidOCDs.elements(); - while (ocds.hasMoreElements()) { - ObjectClassDefinitionImpl ocd = ocds.nextElement(); - if (ocd._localization != null && !localizationFiles.contains(ocd._localization)) - localizationFiles.add(ocd._localization); - } - if (localizationFiles.size() == 0) - localizationFiles.add(getBundleLocalization(_bundle)); - Vector locales = new Vector(7); - Enumeration eLocalizationFiles = localizationFiles.elements(); - while (eLocalizationFiles.hasMoreElements()) { - String localizationFile = eLocalizationFiles.nextElement(); - int iSlash = localizationFile.lastIndexOf(DIRECTORY_SEP); - String baseDir; - String baseFileName; - if (iSlash < 0) { - baseDir = ""; //$NON-NLS-1$ - } else { - baseDir = localizationFile.substring(0, iSlash); - } - baseFileName = '/' + localizationFile + RESOURCE_FILE_CONN; - List entries = wiring.findEntries(baseDir, "*.properties", 0); //$NON-NLS-1$ - if (entries == null) - continue; - for (URL entry : entries) { - String resource = entry.getPath(); - if (resource.startsWith(baseFileName) && resource.toLowerCase().endsWith(RESOURCE_FILE_EXT)) - locales.add(resource.substring(baseFileName.length(), resource.length() - RESOURCE_FILE_EXT.length())); - } - } - _locales = locales.toArray(new String[locales.size()]); - return checkForDefault(_locales); - } - - static String getBundleLocalization(Bundle bundle) { - // Use the Bundle-Localization manifest header value if it exists. - String baseName = bundle.getHeaders("").get(Constants.BUNDLE_LOCALIZATION); //$NON-NLS-1$ - if (baseName == null) - // If the manifest header does not exist, use the default. - baseName = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME; - return baseName; - } - - /** - * Internal Method - checkForDefault - */ - private String[] checkForDefault(String[] locales) { - - if (locales == null || locales.length == 0 || (locales.length == 1 && Locale.getDefault().toString().equals(locales[0]))) - return null; - return locales; - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.EquinoxObjectClassDefinition; + +import java.io.IOException; +import java.net.URL; +import java.util.*; +import javax.xml.parsers.SAXParser; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.Bundle; +import org.osgi.framework.Constants; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.log.LogService; +import org.osgi.service.metatype.MetaTypeProvider; +import org.osgi.service.metatype.MetaTypeService; + +/** + * Implementation of MetaTypeProvider + */ +public class MetaTypeProviderImpl implements MetaTypeProvider { + + public static final String METADATA_NOT_FOUND = "METADATA_NOT_FOUND"; //$NON-NLS-1$ + public static final String OCD_ID_NOT_FOUND = "OCD_ID_NOT_FOUND"; //$NON-NLS-1$ + public static final String ASK_INVALID_LOCALE = "ASK_INVALID_LOCALE"; //$NON-NLS-1$ + + public static final String META_FILE_EXT = ".XML"; //$NON-NLS-1$ + public static final String RESOURCE_FILE_CONN = "_"; //$NON-NLS-1$ + public static final String RESOURCE_FILE_EXT = ".properties"; //$NON-NLS-1$ + public static final char DIRECTORY_SEP = '/'; + + Bundle _bundle; + + Hashtable _allPidOCDs = new Hashtable(7); + Hashtable _allFPidOCDs = new Hashtable(7); + + String[] _locales; + boolean _isThereMeta = false; + + // Give access to subclasses. + protected final LogService logger; + + /** + * Constructor of class MetaTypeProviderImpl. + */ + MetaTypeProviderImpl(Bundle bundle, SAXParser parser, LogService logger) { + + this._bundle = bundle; + this.logger = logger; + + // read all bundle's metadata files and build internal data structures + _isThereMeta = readMetaFiles(bundle, parser); + + if (!_isThereMeta) { + logger.log(LogService.LOG_DEBUG, NLS.bind(MetaTypeMsg.METADATA_NOT_FOUND, new Long(bundle.getBundleId()), bundle.getSymbolicName())); + } + } + + /** + * This method should do the following: + *

- Obtain a SAX parser from the XML Parser Service: + *

+ * + *

	
+ * + * The parser may be SAX 1 (eXML) or SAX 2 (XML4J). It should attempt to use + * a SAX2 parser by instantiating an XMLReader and extending DefaultHandler + * BUT if that fails it should fall back to instantiating a SAX1 Parser and + * extending HandlerBase. + *

- Pass the parser the URL for the bundle's METADATA.XML file + *

- Handle the callbacks from the parser and build the appropriate + * MetaType objects - ObjectClassDefinitions & AttributeDefinitions + * + * @param bundle The bundle object for which the metadata should be read + * @param parserFactory The bundle object for which the metadata should be + * read + * @return void + * @throws IOException If there are errors accessing the metadata.xml file + */ + private boolean readMetaFiles(Bundle bundle, SAXParser saxParser) { + BundleWiring wiring = bundle.adapt(BundleWiring.class); + if (wiring == null) + return false; + List entries = wiring.findEntries(MetaTypeService.METATYPE_DOCUMENTS_LOCATION, "*", 0); //$NON-NLS-1$ + if (entries == null) + return false; + boolean result = false; + for (URL entry : entries) { + if (entry.getPath().endsWith("/")) //$NON-NLS-1$ + continue; + DataParser parser = new DataParser(bundle, entry, saxParser, logger); + try { + Collection designates = parser.doParse(); + if (!designates.isEmpty()) { + result = true; + } + for (Designate designate : designates) { + if (designate.isFactory()) { + _allFPidOCDs.put(designate.getFactoryPid(), designate.getObjectClassDefinition()); + } else { + _allPidOCDs.put(designate.getPid(), designate.getObjectClassDefinition()); + } + } + } catch (Exception e) { + logger.log(LogService.LOG_ERROR, NLS.bind(MetaTypeMsg.METADATA_PARSE_ERROR, new Object[] {entry, bundle.getBundleId()}), e); + } + } + return result; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeProvider#getObjectClassDefinition(java.lang.String, + * java.lang.String) + */ + public EquinoxObjectClassDefinition getObjectClassDefinition(String pid, String locale) { + + if (isInvalidLocale(locale)) { + throw new IllegalArgumentException(NLS.bind(MetaTypeMsg.ASK_INVALID_LOCALE, pid, locale)); + } + + ObjectClassDefinitionImpl ocd; + if (_allPidOCDs.containsKey(pid)) { + ocd = (ObjectClassDefinitionImpl) (_allPidOCDs.get(pid)).clone(); + ocd.setResourceBundle(locale, _bundle); + return ocd; + } else if (_allFPidOCDs.containsKey(pid)) { + ocd = (ObjectClassDefinitionImpl) (_allFPidOCDs.get(pid)).clone(); + ocd.setResourceBundle(locale, _bundle); + return ocd; + } else { + throw new IllegalArgumentException(NLS.bind(MetaTypeMsg.OCD_ID_NOT_FOUND, pid)); + } + } + + /** + * Internal Method - Check if the locale is invalid. + */ + public boolean isInvalidLocale(String locale) { + + // Just a simple and quick check here. + if (locale == null || locale.length() == 0) + return false; + + int idx_first = locale.indexOf(ObjectClassDefinitionImpl.LOCALE_SEP); + int idx_second = locale.lastIndexOf(ObjectClassDefinitionImpl.LOCALE_SEP); + if (idx_first == -1 && locale.length() == 2) + // It is format of only language. + return false; + if ((idx_first == 2) && (idx_second == 5 || idx_second == 2)) + // It is format of language + "_" + country [ + "_" + variation ]. + return false; + return true; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeProvider#getLocales() + */ + public synchronized String[] getLocales() { + + if (_locales != null) + return checkForDefault(_locales); + BundleWiring wiring = _bundle.adapt(BundleWiring.class); + if (wiring == null) + return null; + Vector localizationFiles = new Vector(7); + // get all the localization resources for PIDS + Enumeration ocds = _allPidOCDs.elements(); + while (ocds.hasMoreElements()) { + ObjectClassDefinitionImpl ocd = ocds.nextElement(); + if (ocd._localization != null && !localizationFiles.contains(ocd._localization)) + localizationFiles.add(ocd._localization); + } + // get all the localization resources for FPIDS + ocds = _allFPidOCDs.elements(); + while (ocds.hasMoreElements()) { + ObjectClassDefinitionImpl ocd = ocds.nextElement(); + if (ocd._localization != null && !localizationFiles.contains(ocd._localization)) + localizationFiles.add(ocd._localization); + } + if (localizationFiles.size() == 0) + localizationFiles.add(getBundleLocalization(_bundle)); + Vector locales = new Vector(7); + Enumeration eLocalizationFiles = localizationFiles.elements(); + while (eLocalizationFiles.hasMoreElements()) { + String localizationFile = eLocalizationFiles.nextElement(); + int iSlash = localizationFile.lastIndexOf(DIRECTORY_SEP); + String baseDir; + String baseFileName; + if (iSlash < 0) { + baseDir = ""; //$NON-NLS-1$ + } else { + baseDir = localizationFile.substring(0, iSlash); + } + baseFileName = '/' + localizationFile + RESOURCE_FILE_CONN; + List entries = wiring.findEntries(baseDir, "*.properties", 0); //$NON-NLS-1$ + if (entries == null) + continue; + for (URL entry : entries) { + String resource = entry.getPath(); + if (resource.startsWith(baseFileName) && resource.toLowerCase().endsWith(RESOURCE_FILE_EXT)) + locales.add(resource.substring(baseFileName.length(), resource.length() - RESOURCE_FILE_EXT.length())); + } + } + _locales = locales.toArray(new String[locales.size()]); + return checkForDefault(_locales); + } + + static String getBundleLocalization(Bundle bundle) { + // Use the Bundle-Localization manifest header value if it exists. + String baseName = bundle.getHeaders("").get(Constants.BUNDLE_LOCALIZATION); //$NON-NLS-1$ + if (baseName == null) + // If the manifest header does not exist, use the default. + baseName = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME; + return baseName; + } + + /** + * Internal Method - checkForDefault + */ + private String[] checkForDefault(String[] locales) { + + if (locales == null || locales.length == 0 || (locales.length == 1 && Locale.getDefault().toString().equals(locales[0]))) + return null; + return locales; + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderTracker.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderTracker.java index b7e27ff43..5433cebcf 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderTracker.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeProviderTracker.java @@ -1,287 +1,287 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.*; - -import java.io.IOException; -import java.io.InputStream; -import java.util.*; -import org.eclipse.osgi.util.NLS; -import org.osgi.framework.*; -import org.osgi.service.cm.ManagedService; -import org.osgi.service.cm.ManagedServiceFactory; -import org.osgi.service.log.LogService; -import org.osgi.service.metatype.*; -import org.osgi.util.tracker.ServiceTracker; - -public class MetaTypeProviderTracker implements EquinoxMetaTypeInformation { - private final Bundle _bundle; - private final LogService log; - private final ServiceTracker _tracker; - - /** - * Constructs a MetaTypeProviderTracker which tracks all MetaTypeProviders - * registered by the specified bundle. - * @param context The BundleContext of the MetaTypeService implementation - * @param bundle The bundle to track all MetaTypeProviders for. - * @param log The {@code LogService} to use for logging messages. - */ - public MetaTypeProviderTracker(Bundle bundle, LogService log, ServiceTracker tracker) { - this._bundle = bundle; - this._tracker = tracker; - this.log = log; - } - - private String[] getPids(boolean factory) { - if (_bundle.getState() != Bundle.ACTIVE) - return new String[0]; // return none if not active - MetaTypeProviderWrapper[] wrappers = getMetaTypeProviders(); - ArrayList results = new ArrayList(); - for (int i = 0; i < wrappers.length; i++) { - // return only the correct type of pids (regular or factory) - if (factory == wrappers[i].factory) - results.add(wrappers[i].pid); - } - return results.toArray(new String[results.size()]); - } - - public String[] getPids() { - return getPids(false); - } - - public String[] getFactoryPids() { - return getPids(true); - } - - public Bundle getBundle() { - return _bundle; - } - - public EquinoxObjectClassDefinition getObjectClassDefinition(String id, String locale) { - if (_bundle.getState() != Bundle.ACTIVE) - return null; // return none if not active - MetaTypeProviderWrapper[] wrappers = getMetaTypeProviders(); - for (int i = 0; i < wrappers.length; i++) { - if (id.equals(wrappers[i].pid)) - // found a matching pid now call the actual provider - return wrappers[i].getObjectClassDefinition(id, locale); - } - return null; - } - - public String[] getLocales() { - if (_bundle.getState() != Bundle.ACTIVE) - return new String[0]; // return none if not active - MetaTypeProviderWrapper[] wrappers = getMetaTypeProviders(); - ArrayList locales = new ArrayList(); - // collect all the unique locales from all providers we found - for (int i = 0; i < wrappers.length; i++) { - String[] wrappedLocales = wrappers[i].getLocales(); - if (wrappedLocales == null) - continue; - for (int j = 0; j < wrappedLocales.length; j++) - if (!locales.contains(wrappedLocales[j])) - locales.add(wrappedLocales[j]); - } - return locales.toArray(new String[locales.size()]); - } - - private MetaTypeProviderWrapper[] getMetaTypeProviders() { - Map, Object> services = _tracker.getTracked(); - if (services.isEmpty()) - return new MetaTypeProviderWrapper[0]; - Set> serviceReferences = services.keySet(); - Set result = new HashSet(); - for (ServiceReference serviceReference : serviceReferences) { - if (serviceReference.getBundle() == _bundle) { - Object service = services.get(serviceReference); - // If the service is not a MetaTypeProvider, we're not interested in it. - if (service instanceof MetaTypeProvider) { - // Include the METATYPE_PID, if present, to return as part of getPids(). Also, include the - // METATYPE_FACTORY_PID, if present, to return as part of getFactoryPids(). - // The filter ensures at least one of these properties was set for a standalone MetaTypeProvider. - addMetaTypeProviderWrappers(MetaTypeProvider.METATYPE_PID, serviceReference, (MetaTypeProvider) service, false, result); - addMetaTypeProviderWrappers(MetaTypeProvider.METATYPE_FACTORY_PID, serviceReference, (MetaTypeProvider) service, true, result); - // If the service is a ManagedService, include the SERVICE_PID to return as part of getPids(). - // The filter ensures the SERVICE_PID property was set. - if (service instanceof ManagedService) { - addMetaTypeProviderWrappers(Constants.SERVICE_PID, serviceReference, (MetaTypeProvider) service, false, result); - } - // If the service is a ManagedServiceFactory, include the SERVICE_PID to return as part of getFactoryPids(). - // The filter ensures the SERVICE_PID property was set. - else if (service instanceof ManagedServiceFactory) { - addMetaTypeProviderWrappers(Constants.SERVICE_PID, serviceReference, (MetaTypeProvider) service, true, result); - } - } - } - } - return result.toArray(new MetaTypeProviderWrapper[result.size()]); - } - - private void addMetaTypeProviderWrappers(String servicePropertyName, ServiceReference serviceReference, MetaTypeProvider service, boolean factory, Set wrappers) { - String[] pids = getStringProperty(servicePropertyName, serviceReference.getProperty(servicePropertyName)); - for (String pid : pids) { - wrappers.add(new MetaTypeProviderWrapper(service, pid, factory)); - } - } - - private String[] getStringProperty(String name, Object value) { - // Don't log a warning if the value is null. The filter guarantees at least one of the necessary properties - // is there. If others are not, this method will get called with value equal to null. - if (value == null) - return new String[0]; - if (value instanceof String) { - return new String[] {(String) value}; - } - if (value instanceof String[]) { - return (String[]) value; - } - Exception e = null; - if (value instanceof Collection) { - @SuppressWarnings("unchecked") - Collection temp = (Collection) value; - try { - return temp.toArray(new String[temp.size()]); - } catch (ArrayStoreException ase) { - e = ase; - } - } - log.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_PID_METATYPE_PROVIDER_IGNORED, new Object[] {_bundle.getSymbolicName(), _bundle.getBundleId(), name, value}), e); - return new String[0]; - } - - // this is a simple class just used to temporarily store information about a provider - public class MetaTypeProviderWrapper implements MetaTypeProvider { - private final MetaTypeProvider provider; - final String pid; - final boolean factory; - - MetaTypeProviderWrapper(MetaTypeProvider provider, String pid, boolean factory) { - this.provider = provider; - this.pid = pid; - this.factory = factory; - } - - @Override - public boolean equals(Object object) { - if (object == this) - return true; - if (!(object instanceof MetaTypeProviderWrapper)) - return false; - MetaTypeProviderWrapper that = (MetaTypeProviderWrapper) object; - return this.provider.equals(that.provider) && this.pid.equals(that.pid) && this.factory == that.factory; - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + provider.hashCode(); - result = 31 * result + pid.hashCode(); - result = 31 * result + (factory ? 1 : 0); - return result; - } - - public EquinoxObjectClassDefinition getObjectClassDefinition(String id, String locale) { - final ObjectClassDefinition ocd = provider.getObjectClassDefinition(id, locale); - if (ocd == null) - return null; - return new EquinoxObjectClassDefinition() { - public String getName() { - return ocd.getName(); - } - - public String getID() { - return ocd.getID(); - } - - public String getDescription() { - return ocd.getDescription(); - } - - public InputStream getIcon(int size) throws IOException { - return ocd.getIcon(size); - } - - @SuppressWarnings("unchecked") - public Map getExtensionAttributes(String schema) { - return Collections.EMPTY_MAP; - } - - @SuppressWarnings("unchecked") - public Set getExtensionUris() { - return Collections.EMPTY_SET; - } - - public EquinoxAttributeDefinition[] getAttributeDefinitions(int filter) { - AttributeDefinition[] ads = ocd.getAttributeDefinitions(filter); - if (ads == null || ads.length == 0) - return new EquinoxAttributeDefinition[0]; - Collection result = new ArrayList(ads.length); - for (final AttributeDefinition ad : ads) { - result.add(new EquinoxAttributeDefinition() { - public String getName() { - return ad.getName(); - } - - public String getID() { - return ad.getID(); - } - - public String getDescription() { - return ad.getDescription(); - } - - public int getCardinality() { - return ad.getCardinality(); - } - - public int getType() { - return ad.getType(); - } - - public String[] getOptionValues() { - return ad.getOptionValues(); - } - - public String[] getOptionLabels() { - return ad.getOptionLabels(); - } - - public String validate(String value) { - return ad.validate(value); - } - - public String[] getDefaultValue() { - return ad.getDefaultValue(); - } - - @SuppressWarnings("unchecked") - public Map getExtensionAttributes(String schema) { - return Collections.EMPTY_MAP; - } - - @SuppressWarnings("unchecked") - public Set getExtensionUris() { - return Collections.EMPTY_SET; - } - }); - } - return result.toArray(new EquinoxAttributeDefinition[result.size()]); - } - }; - } - - public String[] getLocales() { - return provider.getLocales(); - } - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.*; +import org.osgi.service.cm.ManagedService; +import org.osgi.service.cm.ManagedServiceFactory; +import org.osgi.service.log.LogService; +import org.osgi.service.metatype.*; +import org.osgi.util.tracker.ServiceTracker; + +public class MetaTypeProviderTracker implements EquinoxMetaTypeInformation { + private final Bundle _bundle; + private final LogService log; + private final ServiceTracker _tracker; + + /** + * Constructs a MetaTypeProviderTracker which tracks all MetaTypeProviders + * registered by the specified bundle. + * @param context The BundleContext of the MetaTypeService implementation + * @param bundle The bundle to track all MetaTypeProviders for. + * @param log The {@code LogService} to use for logging messages. + */ + public MetaTypeProviderTracker(Bundle bundle, LogService log, ServiceTracker tracker) { + this._bundle = bundle; + this._tracker = tracker; + this.log = log; + } + + private String[] getPids(boolean factory) { + if (_bundle.getState() != Bundle.ACTIVE) + return new String[0]; // return none if not active + MetaTypeProviderWrapper[] wrappers = getMetaTypeProviders(); + ArrayList results = new ArrayList(); + for (int i = 0; i < wrappers.length; i++) { + // return only the correct type of pids (regular or factory) + if (factory == wrappers[i].factory) + results.add(wrappers[i].pid); + } + return results.toArray(new String[results.size()]); + } + + public String[] getPids() { + return getPids(false); + } + + public String[] getFactoryPids() { + return getPids(true); + } + + public Bundle getBundle() { + return _bundle; + } + + public EquinoxObjectClassDefinition getObjectClassDefinition(String id, String locale) { + if (_bundle.getState() != Bundle.ACTIVE) + return null; // return none if not active + MetaTypeProviderWrapper[] wrappers = getMetaTypeProviders(); + for (int i = 0; i < wrappers.length; i++) { + if (id.equals(wrappers[i].pid)) + // found a matching pid now call the actual provider + return wrappers[i].getObjectClassDefinition(id, locale); + } + return null; + } + + public String[] getLocales() { + if (_bundle.getState() != Bundle.ACTIVE) + return new String[0]; // return none if not active + MetaTypeProviderWrapper[] wrappers = getMetaTypeProviders(); + ArrayList locales = new ArrayList(); + // collect all the unique locales from all providers we found + for (int i = 0; i < wrappers.length; i++) { + String[] wrappedLocales = wrappers[i].getLocales(); + if (wrappedLocales == null) + continue; + for (int j = 0; j < wrappedLocales.length; j++) + if (!locales.contains(wrappedLocales[j])) + locales.add(wrappedLocales[j]); + } + return locales.toArray(new String[locales.size()]); + } + + private MetaTypeProviderWrapper[] getMetaTypeProviders() { + Map, Object> services = _tracker.getTracked(); + if (services.isEmpty()) + return new MetaTypeProviderWrapper[0]; + Set> serviceReferences = services.keySet(); + Set result = new HashSet(); + for (ServiceReference serviceReference : serviceReferences) { + if (serviceReference.getBundle() == _bundle) { + Object service = services.get(serviceReference); + // If the service is not a MetaTypeProvider, we're not interested in it. + if (service instanceof MetaTypeProvider) { + // Include the METATYPE_PID, if present, to return as part of getPids(). Also, include the + // METATYPE_FACTORY_PID, if present, to return as part of getFactoryPids(). + // The filter ensures at least one of these properties was set for a standalone MetaTypeProvider. + addMetaTypeProviderWrappers(MetaTypeProvider.METATYPE_PID, serviceReference, (MetaTypeProvider) service, false, result); + addMetaTypeProviderWrappers(MetaTypeProvider.METATYPE_FACTORY_PID, serviceReference, (MetaTypeProvider) service, true, result); + // If the service is a ManagedService, include the SERVICE_PID to return as part of getPids(). + // The filter ensures the SERVICE_PID property was set. + if (service instanceof ManagedService) { + addMetaTypeProviderWrappers(Constants.SERVICE_PID, serviceReference, (MetaTypeProvider) service, false, result); + } + // If the service is a ManagedServiceFactory, include the SERVICE_PID to return as part of getFactoryPids(). + // The filter ensures the SERVICE_PID property was set. + else if (service instanceof ManagedServiceFactory) { + addMetaTypeProviderWrappers(Constants.SERVICE_PID, serviceReference, (MetaTypeProvider) service, true, result); + } + } + } + } + return result.toArray(new MetaTypeProviderWrapper[result.size()]); + } + + private void addMetaTypeProviderWrappers(String servicePropertyName, ServiceReference serviceReference, MetaTypeProvider service, boolean factory, Set wrappers) { + String[] pids = getStringProperty(servicePropertyName, serviceReference.getProperty(servicePropertyName)); + for (String pid : pids) { + wrappers.add(new MetaTypeProviderWrapper(service, pid, factory)); + } + } + + private String[] getStringProperty(String name, Object value) { + // Don't log a warning if the value is null. The filter guarantees at least one of the necessary properties + // is there. If others are not, this method will get called with value equal to null. + if (value == null) + return new String[0]; + if (value instanceof String) { + return new String[] {(String) value}; + } + if (value instanceof String[]) { + return (String[]) value; + } + Exception e = null; + if (value instanceof Collection) { + @SuppressWarnings("unchecked") + Collection temp = (Collection) value; + try { + return temp.toArray(new String[temp.size()]); + } catch (ArrayStoreException ase) { + e = ase; + } + } + log.log(LogService.LOG_WARNING, NLS.bind(MetaTypeMsg.INVALID_PID_METATYPE_PROVIDER_IGNORED, new Object[] {_bundle.getSymbolicName(), _bundle.getBundleId(), name, value}), e); + return new String[0]; + } + + // this is a simple class just used to temporarily store information about a provider + public class MetaTypeProviderWrapper implements MetaTypeProvider { + private final MetaTypeProvider provider; + final String pid; + final boolean factory; + + MetaTypeProviderWrapper(MetaTypeProvider provider, String pid, boolean factory) { + this.provider = provider; + this.pid = pid; + this.factory = factory; + } + + @Override + public boolean equals(Object object) { + if (object == this) + return true; + if (!(object instanceof MetaTypeProviderWrapper)) + return false; + MetaTypeProviderWrapper that = (MetaTypeProviderWrapper) object; + return this.provider.equals(that.provider) && this.pid.equals(that.pid) && this.factory == that.factory; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + provider.hashCode(); + result = 31 * result + pid.hashCode(); + result = 31 * result + (factory ? 1 : 0); + return result; + } + + public EquinoxObjectClassDefinition getObjectClassDefinition(String id, String locale) { + final ObjectClassDefinition ocd = provider.getObjectClassDefinition(id, locale); + if (ocd == null) + return null; + return new EquinoxObjectClassDefinition() { + public String getName() { + return ocd.getName(); + } + + public String getID() { + return ocd.getID(); + } + + public String getDescription() { + return ocd.getDescription(); + } + + public InputStream getIcon(int size) throws IOException { + return ocd.getIcon(size); + } + + @SuppressWarnings("unchecked") + public Map getExtensionAttributes(String schema) { + return Collections.EMPTY_MAP; + } + + @SuppressWarnings("unchecked") + public Set getExtensionUris() { + return Collections.EMPTY_SET; + } + + public EquinoxAttributeDefinition[] getAttributeDefinitions(int filter) { + AttributeDefinition[] ads = ocd.getAttributeDefinitions(filter); + if (ads == null || ads.length == 0) + return new EquinoxAttributeDefinition[0]; + Collection result = new ArrayList(ads.length); + for (final AttributeDefinition ad : ads) { + result.add(new EquinoxAttributeDefinition() { + public String getName() { + return ad.getName(); + } + + public String getID() { + return ad.getID(); + } + + public String getDescription() { + return ad.getDescription(); + } + + public int getCardinality() { + return ad.getCardinality(); + } + + public int getType() { + return ad.getType(); + } + + public String[] getOptionValues() { + return ad.getOptionValues(); + } + + public String[] getOptionLabels() { + return ad.getOptionLabels(); + } + + public String validate(String value) { + return ad.validate(value); + } + + public String[] getDefaultValue() { + return ad.getDefaultValue(); + } + + @SuppressWarnings("unchecked") + public Map getExtensionAttributes(String schema) { + return Collections.EMPTY_MAP; + } + + @SuppressWarnings("unchecked") + public Set getExtensionUris() { + return Collections.EMPTY_SET; + } + }); + } + return result.toArray(new EquinoxAttributeDefinition[result.size()]); + } + }; + } + + public String[] getLocales() { + return provider.getLocales(); + } + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeServiceImpl.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeServiceImpl.java index 6adf79321..28175be44 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeServiceImpl.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/MetaTypeServiceImpl.java @@ -1,137 +1,137 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.EquinoxMetaTypeInformation; -import org.eclipse.equinox.metatype.EquinoxMetaTypeService; - -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; -import java.util.Hashtable; -import javax.xml.parsers.*; -import org.eclipse.osgi.util.NLS; -import org.osgi.framework.*; -import org.osgi.service.log.LogService; -import org.osgi.util.tracker.ServiceTracker; -import org.xml.sax.SAXException; - -/** - * Implementation of MetaTypeService - */ -public class MetaTypeServiceImpl implements EquinoxMetaTypeService, SynchronousBundleListener { - - SAXParserFactory _parserFactory; - private Hashtable _mtps = new Hashtable(7); - - private final LogService logger; - private final ServiceTracker metaTypeProviderTracker; - - /** - * Constructor of class MetaTypeServiceImpl. - */ - public MetaTypeServiceImpl(SAXParserFactory parserFactory, LogService logger, ServiceTracker metaTypeProviderTracker) { - this._parserFactory = parserFactory; - this.logger = logger; - this.metaTypeProviderTracker = metaTypeProviderTracker; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.MetaTypeService#getMetaTypeInformation(org.osgi.framework.Bundle) - */ - public EquinoxMetaTypeInformation getMetaTypeInformation(Bundle bundle) { - return getMetaTypeProvider(bundle); - } - - /** - * Internal Method - to get MetaTypeProvider object. - */ - private EquinoxMetaTypeInformation getMetaTypeProvider(final Bundle b) { - final LogService loggerTemp = this.logger; - final ServiceTracker tracker = this.metaTypeProviderTracker; - try { - Long bID = new Long(b.getBundleId()); - synchronized (_mtps) { - if (_mtps.containsKey(bID)) - return _mtps.get(bID); - // Avoid synthetic accessor method warnings. - - EquinoxMetaTypeInformation mti = AccessController.doPrivileged(new PrivilegedExceptionAction() { - public EquinoxMetaTypeInformation run() throws ParserConfigurationException, SAXException { - MetaTypeInformationImpl impl = new MetaTypeInformationImpl(b, newParser(), loggerTemp); - if (!impl._isThereMeta) - return new MetaTypeProviderTracker(b, loggerTemp, tracker); - return impl; - } - }); - _mtps.put(bID, mti); - return mti; - } - } catch (Exception e) { - logger.log(LogService.LOG_ERROR, NLS.bind(MetaTypeMsg.EXCEPTION_MESSAGE, e.getMessage()), e); - return new MetaTypeProviderTracker(b, loggerTemp, tracker); - } - } - - SAXParser newParser() throws ParserConfigurationException, SAXException { - boolean namespaceAware = _parserFactory.isNamespaceAware(); - boolean validating = _parserFactory.isValidating(); - // Always want a non-validating parser. - _parserFactory.setValidating(false); - try { - // If the factory is already namespace aware, we know it can create namespace aware parsers - // because that was checked in the service tracker. - if (namespaceAware) { - return _parserFactory.newSAXParser(); - } - // If the factory is not already namespace aware, it may or may not be able to create - // namespace aware parsers. - _parserFactory.setNamespaceAware(true); - try { - return _parserFactory.newSAXParser(); - } catch (Exception e) { - // Factory cannot create namespace aware parsers. Go with the last resort. - _parserFactory.setNamespaceAware(false); - return _parserFactory.newSAXParser(); - } - } finally { - // Restore the previous settings in all cases. - _parserFactory.setNamespaceAware(namespaceAware); - _parserFactory.setValidating(validating); - } - } - - /* - * (non-Javadoc) - * - * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent) - */ - public void bundleChanged(BundleEvent event) { - - int type = event.getType(); - Long bID = new Long(event.getBundle().getBundleId()); - - switch (type) { - case BundleEvent.UPDATED : - case BundleEvent.UNINSTALLED : - _mtps.remove(bID); - break; - case BundleEvent.INSTALLED : - case BundleEvent.RESOLVED : - case BundleEvent.STARTED : - case BundleEvent.STOPPED : - case BundleEvent.UNRESOLVED : - default : - break; - } - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.EquinoxMetaTypeInformation; +import org.eclipse.equinox.metatype.EquinoxMetaTypeService; + +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.util.Hashtable; +import javax.xml.parsers.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.*; +import org.osgi.service.log.LogService; +import org.osgi.util.tracker.ServiceTracker; +import org.xml.sax.SAXException; + +/** + * Implementation of MetaTypeService + */ +public class MetaTypeServiceImpl implements EquinoxMetaTypeService, SynchronousBundleListener { + + SAXParserFactory _parserFactory; + private Hashtable _mtps = new Hashtable(7); + + private final LogService logger; + private final ServiceTracker metaTypeProviderTracker; + + /** + * Constructor of class MetaTypeServiceImpl. + */ + public MetaTypeServiceImpl(SAXParserFactory parserFactory, LogService logger, ServiceTracker metaTypeProviderTracker) { + this._parserFactory = parserFactory; + this.logger = logger; + this.metaTypeProviderTracker = metaTypeProviderTracker; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.MetaTypeService#getMetaTypeInformation(org.osgi.framework.Bundle) + */ + public EquinoxMetaTypeInformation getMetaTypeInformation(Bundle bundle) { + return getMetaTypeProvider(bundle); + } + + /** + * Internal Method - to get MetaTypeProvider object. + */ + private EquinoxMetaTypeInformation getMetaTypeProvider(final Bundle b) { + final LogService loggerTemp = this.logger; + final ServiceTracker tracker = this.metaTypeProviderTracker; + try { + Long bID = new Long(b.getBundleId()); + synchronized (_mtps) { + if (_mtps.containsKey(bID)) + return _mtps.get(bID); + // Avoid synthetic accessor method warnings. + + EquinoxMetaTypeInformation mti = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public EquinoxMetaTypeInformation run() throws ParserConfigurationException, SAXException { + MetaTypeInformationImpl impl = new MetaTypeInformationImpl(b, newParser(), loggerTemp); + if (!impl._isThereMeta) + return new MetaTypeProviderTracker(b, loggerTemp, tracker); + return impl; + } + }); + _mtps.put(bID, mti); + return mti; + } + } catch (Exception e) { + logger.log(LogService.LOG_ERROR, NLS.bind(MetaTypeMsg.EXCEPTION_MESSAGE, e.getMessage()), e); + return new MetaTypeProviderTracker(b, loggerTemp, tracker); + } + } + + SAXParser newParser() throws ParserConfigurationException, SAXException { + boolean namespaceAware = _parserFactory.isNamespaceAware(); + boolean validating = _parserFactory.isValidating(); + // Always want a non-validating parser. + _parserFactory.setValidating(false); + try { + // If the factory is already namespace aware, we know it can create namespace aware parsers + // because that was checked in the service tracker. + if (namespaceAware) { + return _parserFactory.newSAXParser(); + } + // If the factory is not already namespace aware, it may or may not be able to create + // namespace aware parsers. + _parserFactory.setNamespaceAware(true); + try { + return _parserFactory.newSAXParser(); + } catch (Exception e) { + // Factory cannot create namespace aware parsers. Go with the last resort. + _parserFactory.setNamespaceAware(false); + return _parserFactory.newSAXParser(); + } + } finally { + // Restore the previous settings in all cases. + _parserFactory.setNamespaceAware(namespaceAware); + _parserFactory.setValidating(validating); + } + } + + /* + * (non-Javadoc) + * + * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent) + */ + public void bundleChanged(BundleEvent event) { + + int type = event.getType(); + Long bID = new Long(event.getBundle().getBundleId()); + + switch (type) { + case BundleEvent.UPDATED : + case BundleEvent.UNINSTALLED : + _mtps.remove(bID); + break; + case BundleEvent.INSTALLED : + case BundleEvent.RESOLVED : + case BundleEvent.STARTED : + case BundleEvent.STOPPED : + case BundleEvent.UNRESOLVED : + default : + break; + } + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ObjectClassDefinitionImpl.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ObjectClassDefinitionImpl.java index 22d0f76ad..6cc887983 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ObjectClassDefinitionImpl.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ObjectClassDefinitionImpl.java @@ -1,320 +1,320 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import org.eclipse.equinox.metatype.EquinoxAttributeDefinition; -import org.eclipse.equinox.metatype.EquinoxObjectClassDefinition; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.*; -import org.osgi.framework.Bundle; - -/** - * Implementation of ObjectClassDefinition - */ -public class ObjectClassDefinitionImpl extends LocalizationElement implements EquinoxObjectClassDefinition, Cloneable { - - public static final char LOCALE_SEP = '_'; - - String _name; - String _id; - String _description; - - int _type; - Vector _required = new Vector(7); - Vector _optional = new Vector(7); - Icon _icon; - - private final ExtendableHelper helper; - - /* - * Constructor of class ObjectClassDefinitionImpl. - */ - public ObjectClassDefinitionImpl(String name, String description, String id, String localization, Map> extensionAttributes) { - this(name, description, id, 0, localization, new ExtendableHelper(extensionAttributes)); - } - - /* - * Constructor of class ObjectClassDefinitionImpl. - */ - public ObjectClassDefinitionImpl(String name, String description, String id, int type, String localization, ExtendableHelper helper) { - this._name = name; - this._id = id; - this._description = description; - this._type = type; - this._localization = localization; - this.helper = helper; - } - - /* - * - */ - public synchronized Object clone() { - - ObjectClassDefinitionImpl ocd = new ObjectClassDefinitionImpl(_name, _description, _id, _type, _localization, helper); - for (int i = 0; i < _required.size(); i++) { - AttributeDefinitionImpl ad = _required.elementAt(i); - ocd.addAttributeDefinition((AttributeDefinitionImpl) ad.clone(), true); - } - for (int i = 0; i < _optional.size(); i++) { - AttributeDefinitionImpl ad = _optional.elementAt(i); - ocd.addAttributeDefinition((AttributeDefinitionImpl) ad.clone(), false); - } - if (_icon != null) { - ocd.setIcon((Icon) _icon.clone()); - } - return ocd; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.ObjectClassDefinition#getName() - */ - public String getName() { - return getLocalized(_name); - } - - /** - * Method to set the name of ObjectClassDefinition. - */ - void setName(String name) { - this._name = name; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.ObjectClassDefinition#getID() - */ - public String getID() { - return _id; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.ObjectClassDefinition#getDescription() - */ - public String getDescription() { - return getLocalized(_description); - } - - /* - * Method to set the description of ObjectClassDefinition. - */ - void setDescription(String description) { - this._description = description; - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.ObjectClassDefinition#getAttributeDefinitions(int) - */ - public EquinoxAttributeDefinition[] getAttributeDefinitions(int filter) { - - EquinoxAttributeDefinition[] atts; - switch (filter) { - case REQUIRED : - atts = new EquinoxAttributeDefinition[_required.size()]; - _required.toArray(atts); - return atts; - case OPTIONAL : - atts = new EquinoxAttributeDefinition[_optional.size()]; - _optional.toArray(atts); - return atts; - case ALL : - default : - atts = new EquinoxAttributeDefinition[_required.size() + _optional.size()]; - Enumeration e = _required.elements(); - int i = 0; - while (e.hasMoreElements()) { - atts[i] = e.nextElement(); - i++; - } - e = _optional.elements(); - while (e.hasMoreElements()) { - atts[i] = e.nextElement(); - i++; - } - return atts; - } - } - - /* - * Method to add one new AD to ObjectClassDefinition. - */ - void addAttributeDefinition(AttributeDefinitionImpl ad, boolean isRequired) { - - if (isRequired) { - _required.addElement(ad); - } else { - _optional.addElement(ad); - } - } - - /* - * (non-Javadoc) - * - * @see org.osgi.service.metatype.ObjectClassDefinition#getIcon(int) - */ - public InputStream getIcon(int sizeHint) throws IOException { - // The parameter simply represents a requested size. This method should never return null if an - // icon exists. - // TODO This method may change further depending on the outcome of certain ongoing CPEG discussions. - // It is thought that users should be able to specify the same icon multiple times but of different - // sizes. This would require a change to the XML schema. This method would then return the icon with - // a size closest to the requested size. - if ((_icon == null)) { - return null; - } - Bundle b = _icon.getIconBundle(); - URL[] urls = FragmentUtils.findEntries(b, getLocalized(_icon.getIconName())); - if (urls != null && urls.length > 0) { - return urls[0].openStream(); - } - return null; - } - - /** - * Method to set the icon of ObjectClassDefinition. - */ - void setIcon(Icon icon) { - this._icon = icon; - } - - /** - * Method to set the resource bundle for this OCD and all its ADs. - */ - void setResourceBundle(String assignedLocale, Bundle bundle) { - - _rb = getResourceBundle(assignedLocale, bundle); - - Enumeration allADReqs = _required.elements(); - while (allADReqs.hasMoreElements()) { - AttributeDefinitionImpl ad = allADReqs.nextElement(); - ad.setResourceBundle(_rb); - } - - Enumeration allADOpts = _optional.elements(); - while (allADOpts.hasMoreElements()) { - AttributeDefinitionImpl ad = allADOpts.nextElement(); - ad.setResourceBundle(_rb); - } - } - - /* - * Internal Method - to get resource bundle. - */ - private ResourceBundle getResourceBundle(String locale, final Bundle bundle) { - // Determine the base name of the bundle localization property files. - // If the 'localization' attribute was not specified, - // use the Bundle-Localization manifest header value instead if it exists. - String resourceBase = _localization != null ? _localization : MetaTypeProviderImpl.getBundleLocalization(bundle); - - // There are seven searching candidates possible: - // baseName + - // "_" + language1 + "_" + country1 + "_" + variation1 + ".properties" - // or "_" + language1 + "_" + country1 + ".properties" - // or "_" + language1 + ".properties" - // or "_" + language2 + "_" + country2 + "_" + variation2 + ".properties" - // or "_" + language2 + "_" + country2 + ".properties" - // or "_" + language2 + ".properties" - // or "" + ".properties" - // - // Where language1[_country1[_variation1]] is the requested locale, - // and language2[_country2[_variation2]] is the default locale. - - String[] searchCandidates = new String[7]; - - // Candidates from passed locale: - if (locale != null && locale.length() > 0) { - int idx1_first = locale.indexOf(LOCALE_SEP); - if (idx1_first == -1) { - // locale has only language. - searchCandidates[2] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale; - } else { - // locale has at least language and country. - searchCandidates[2] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale.substring(0, idx1_first); - int idx1_second = locale.indexOf(LOCALE_SEP, idx1_first + 1); - if (idx1_second == -1) { - // locale just has both language and country. - searchCandidates[1] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale; - } else { - // locale has language, country, and variation all. - searchCandidates[1] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale.substring(0, idx1_second); - searchCandidates[0] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale; - } - } - } - - // Candidates from Locale.getDefault(): - String defaultLocale = Locale.getDefault().toString(); - int idx2_first = defaultLocale.indexOf(LOCALE_SEP); - int idx2_second = defaultLocale.indexOf(LOCALE_SEP, idx2_first + 1); - if (idx2_second != -1) { - // default-locale is format of [language]_[country]_variation. - searchCandidates[3] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + defaultLocale; - if (searchCandidates[3].equalsIgnoreCase(searchCandidates[0])) { - searchCandidates[3] = null; - } - } - if ((idx2_first != -1) && (idx2_second != idx2_first + 1)) { - // default-locale is format of [language]_country[_variation]. - searchCandidates[4] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + ((idx2_second == -1) ? defaultLocale : defaultLocale.substring(0, idx2_second)); - if (searchCandidates[4].equalsIgnoreCase(searchCandidates[1])) { - searchCandidates[4] = null; - } - } - if ((idx2_first == -1) && (defaultLocale.length() > 0)) { - // default-locale has only language. - searchCandidates[5] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + defaultLocale; - } else if (idx2_first > 0) { - // default-locale is format of language_[...]. - searchCandidates[5] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + defaultLocale.substring(0, idx2_first); - } - if (searchCandidates[5] != null && searchCandidates[5].equalsIgnoreCase(searchCandidates[2])) { - searchCandidates[5] = null; - } - - // The final candidate. - searchCandidates[6] = ""; //$NON-NLS-1$ - - URL resourceUrl = null; - URL[] urls = null; - - for (int idx = 0; (idx < searchCandidates.length) && (resourceUrl == null); idx++) { - urls = (searchCandidates[idx] == null ? null : FragmentUtils.findEntries(bundle, resourceBase + searchCandidates[idx] + MetaTypeProviderImpl.RESOURCE_FILE_EXT)); - if (urls != null && urls.length > 0) - resourceUrl = urls[0]; - } - - if (resourceUrl != null) { - try { - return new PropertyResourceBundle(resourceUrl.openStream()); - } catch (IOException ioe) { - // Exception when creating PropertyResourceBundle object. - } - } - return null; - } - - public Map getExtensionAttributes(String schema) { - return helper.getExtensionAttributes(schema); - } - - public Set getExtensionUris() { - return helper.getExtensionUris(); - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import org.eclipse.equinox.metatype.EquinoxAttributeDefinition; +import org.eclipse.equinox.metatype.EquinoxObjectClassDefinition; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.*; +import org.osgi.framework.Bundle; + +/** + * Implementation of ObjectClassDefinition + */ +public class ObjectClassDefinitionImpl extends LocalizationElement implements EquinoxObjectClassDefinition, Cloneable { + + public static final char LOCALE_SEP = '_'; + + String _name; + String _id; + String _description; + + int _type; + Vector _required = new Vector(7); + Vector _optional = new Vector(7); + Icon _icon; + + private final ExtendableHelper helper; + + /* + * Constructor of class ObjectClassDefinitionImpl. + */ + public ObjectClassDefinitionImpl(String name, String description, String id, String localization, Map> extensionAttributes) { + this(name, description, id, 0, localization, new ExtendableHelper(extensionAttributes)); + } + + /* + * Constructor of class ObjectClassDefinitionImpl. + */ + public ObjectClassDefinitionImpl(String name, String description, String id, int type, String localization, ExtendableHelper helper) { + this._name = name; + this._id = id; + this._description = description; + this._type = type; + this._localization = localization; + this.helper = helper; + } + + /* + * + */ + public synchronized Object clone() { + + ObjectClassDefinitionImpl ocd = new ObjectClassDefinitionImpl(_name, _description, _id, _type, _localization, helper); + for (int i = 0; i < _required.size(); i++) { + AttributeDefinitionImpl ad = _required.elementAt(i); + ocd.addAttributeDefinition((AttributeDefinitionImpl) ad.clone(), true); + } + for (int i = 0; i < _optional.size(); i++) { + AttributeDefinitionImpl ad = _optional.elementAt(i); + ocd.addAttributeDefinition((AttributeDefinitionImpl) ad.clone(), false); + } + if (_icon != null) { + ocd.setIcon((Icon) _icon.clone()); + } + return ocd; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getName() + */ + public String getName() { + return getLocalized(_name); + } + + /** + * Method to set the name of ObjectClassDefinition. + */ + void setName(String name) { + this._name = name; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getID() + */ + public String getID() { + return _id; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getDescription() + */ + public String getDescription() { + return getLocalized(_description); + } + + /* + * Method to set the description of ObjectClassDefinition. + */ + void setDescription(String description) { + this._description = description; + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getAttributeDefinitions(int) + */ + public EquinoxAttributeDefinition[] getAttributeDefinitions(int filter) { + + EquinoxAttributeDefinition[] atts; + switch (filter) { + case REQUIRED : + atts = new EquinoxAttributeDefinition[_required.size()]; + _required.toArray(atts); + return atts; + case OPTIONAL : + atts = new EquinoxAttributeDefinition[_optional.size()]; + _optional.toArray(atts); + return atts; + case ALL : + default : + atts = new EquinoxAttributeDefinition[_required.size() + _optional.size()]; + Enumeration e = _required.elements(); + int i = 0; + while (e.hasMoreElements()) { + atts[i] = e.nextElement(); + i++; + } + e = _optional.elements(); + while (e.hasMoreElements()) { + atts[i] = e.nextElement(); + i++; + } + return atts; + } + } + + /* + * Method to add one new AD to ObjectClassDefinition. + */ + void addAttributeDefinition(AttributeDefinitionImpl ad, boolean isRequired) { + + if (isRequired) { + _required.addElement(ad); + } else { + _optional.addElement(ad); + } + } + + /* + * (non-Javadoc) + * + * @see org.osgi.service.metatype.ObjectClassDefinition#getIcon(int) + */ + public InputStream getIcon(int sizeHint) throws IOException { + // The parameter simply represents a requested size. This method should never return null if an + // icon exists. + // TODO This method may change further depending on the outcome of certain ongoing CPEG discussions. + // It is thought that users should be able to specify the same icon multiple times but of different + // sizes. This would require a change to the XML schema. This method would then return the icon with + // a size closest to the requested size. + if ((_icon == null)) { + return null; + } + Bundle b = _icon.getIconBundle(); + URL[] urls = FragmentUtils.findEntries(b, getLocalized(_icon.getIconName())); + if (urls != null && urls.length > 0) { + return urls[0].openStream(); + } + return null; + } + + /** + * Method to set the icon of ObjectClassDefinition. + */ + void setIcon(Icon icon) { + this._icon = icon; + } + + /** + * Method to set the resource bundle for this OCD and all its ADs. + */ + void setResourceBundle(String assignedLocale, Bundle bundle) { + + _rb = getResourceBundle(assignedLocale, bundle); + + Enumeration allADReqs = _required.elements(); + while (allADReqs.hasMoreElements()) { + AttributeDefinitionImpl ad = allADReqs.nextElement(); + ad.setResourceBundle(_rb); + } + + Enumeration allADOpts = _optional.elements(); + while (allADOpts.hasMoreElements()) { + AttributeDefinitionImpl ad = allADOpts.nextElement(); + ad.setResourceBundle(_rb); + } + } + + /* + * Internal Method - to get resource bundle. + */ + private ResourceBundle getResourceBundle(String locale, final Bundle bundle) { + // Determine the base name of the bundle localization property files. + // If the 'localization' attribute was not specified, + // use the Bundle-Localization manifest header value instead if it exists. + String resourceBase = _localization != null ? _localization : MetaTypeProviderImpl.getBundleLocalization(bundle); + + // There are seven searching candidates possible: + // baseName + + // "_" + language1 + "_" + country1 + "_" + variation1 + ".properties" + // or "_" + language1 + "_" + country1 + ".properties" + // or "_" + language1 + ".properties" + // or "_" + language2 + "_" + country2 + "_" + variation2 + ".properties" + // or "_" + language2 + "_" + country2 + ".properties" + // or "_" + language2 + ".properties" + // or "" + ".properties" + // + // Where language1[_country1[_variation1]] is the requested locale, + // and language2[_country2[_variation2]] is the default locale. + + String[] searchCandidates = new String[7]; + + // Candidates from passed locale: + if (locale != null && locale.length() > 0) { + int idx1_first = locale.indexOf(LOCALE_SEP); + if (idx1_first == -1) { + // locale has only language. + searchCandidates[2] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale; + } else { + // locale has at least language and country. + searchCandidates[2] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale.substring(0, idx1_first); + int idx1_second = locale.indexOf(LOCALE_SEP, idx1_first + 1); + if (idx1_second == -1) { + // locale just has both language and country. + searchCandidates[1] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale; + } else { + // locale has language, country, and variation all. + searchCandidates[1] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale.substring(0, idx1_second); + searchCandidates[0] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + locale; + } + } + } + + // Candidates from Locale.getDefault(): + String defaultLocale = Locale.getDefault().toString(); + int idx2_first = defaultLocale.indexOf(LOCALE_SEP); + int idx2_second = defaultLocale.indexOf(LOCALE_SEP, idx2_first + 1); + if (idx2_second != -1) { + // default-locale is format of [language]_[country]_variation. + searchCandidates[3] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + defaultLocale; + if (searchCandidates[3].equalsIgnoreCase(searchCandidates[0])) { + searchCandidates[3] = null; + } + } + if ((idx2_first != -1) && (idx2_second != idx2_first + 1)) { + // default-locale is format of [language]_country[_variation]. + searchCandidates[4] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + ((idx2_second == -1) ? defaultLocale : defaultLocale.substring(0, idx2_second)); + if (searchCandidates[4].equalsIgnoreCase(searchCandidates[1])) { + searchCandidates[4] = null; + } + } + if ((idx2_first == -1) && (defaultLocale.length() > 0)) { + // default-locale has only language. + searchCandidates[5] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + defaultLocale; + } else if (idx2_first > 0) { + // default-locale is format of language_[...]. + searchCandidates[5] = MetaTypeProviderImpl.RESOURCE_FILE_CONN + defaultLocale.substring(0, idx2_first); + } + if (searchCandidates[5] != null && searchCandidates[5].equalsIgnoreCase(searchCandidates[2])) { + searchCandidates[5] = null; + } + + // The final candidate. + searchCandidates[6] = ""; //$NON-NLS-1$ + + URL resourceUrl = null; + URL[] urls = null; + + for (int idx = 0; (idx < searchCandidates.length) && (resourceUrl == null); idx++) { + urls = (searchCandidates[idx] == null ? null : FragmentUtils.findEntries(bundle, resourceBase + searchCandidates[idx] + MetaTypeProviderImpl.RESOURCE_FILE_EXT)); + if (urls != null && urls.length > 0) + resourceUrl = urls[0]; + } + + if (resourceUrl != null) { + try { + return new PropertyResourceBundle(resourceUrl.openStream()); + } catch (IOException ioe) { + // Exception when creating PropertyResourceBundle object. + } + } + return null; + } + + public Map getExtensionAttributes(String schema) { + return helper.getExtensionAttributes(schema); + } + + public Set getExtensionUris() { + return helper.getExtensionUris(); + } +} diff --git a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ValueTokenizer.java b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ValueTokenizer.java index 6c868d772..c0c5914f3 100644 --- a/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ValueTokenizer.java +++ b/bundles/org.eclipse.equinox.metatype/src/org/eclipse/equinox/metatype/impl/ValueTokenizer.java @@ -1,274 +1,274 @@ -/******************************************************************************* - * Copyright (c) 2005, 2011 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.metatype.impl; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.*; -import org.eclipse.osgi.util.NLS; -import org.osgi.service.log.LogService; -import org.osgi.service.metatype.AttributeDefinition; - -public class ValueTokenizer { - private static final char DELIMITER = ','; - private static final char ESCAPE = '\\'; - - private final LogService logger; - private final List values = new ArrayList(); - - /* - * Constructor of class ValueTokenizer - */ - public ValueTokenizer(String values_str, LogService logger) { - this.logger = logger; - if (values_str == null) - return; - // The trick is to strip out unescaped whitespace characters before and - // after the input string as well as before and after each - // individual token within the input string without losing any escaped - // whitespace characters. Whitespace between two non-whitespace - // characters may or may not be escaped. Also, any character may be - // escaped. The escape character is '\'. The delimiter is ','. - StringBuffer buffer = new StringBuffer(); - // Loop over the characters within the input string and extract each - // value token. - for (int i = 0; i < values_str.length(); i++) { - char c1 = values_str.charAt(i); - switch (c1) { - case DELIMITER : - // When the delimiter is encountered, add the extracted - // token to the result and prepare the buffer to receive the - // next token. - values.add(buffer.toString()); - buffer.delete(0, buffer.length()); - break; - case ESCAPE : - // When the escape is encountered, add the immediately - // following character to the token, unless the end of the - // input has been reached. Note this will result in loop - // counter 'i' being incremented twice, once here and once - // at the end of the loop. - if (i + 1 < values_str.length()) { - buffer.append(values_str.charAt(++i)); - } else { - // If the ESCAPE character occurs as the last character - // of the string, log the error and ignore it. - logger.log(LogService.LOG_ERROR, "ValueTokenizer.ValueTokenizer(String) " + MetaTypeMsg.TOKENIZER_GOT_INVALID_DATA); //$NON-NLS-1$ - } - break; - default : - // For all other characters, add them to the current token - // unless dealing with unescaped whitespace at the beginning - // or end. We know the whitespace is unescaped because it - // would have been handled in the ESCAPE case otherwise. - if (Character.isWhitespace(c1)) { - // Ignore unescaped whitespace at the beginning of the - // token. - if (buffer.length() == 0) { - continue; - } - // If the whitespace is not at the beginning, look - // forward, starting with the next character, to see if - // it's in the middle or at the end. Unescaped - // whitespace in the middle is okay. - for (int j = i + 1; j < values_str.length(); j++) { - // Keep looping until the end of the string is - // reached or a non-whitespace character other than - // the escape is seen. - char c2 = values_str.charAt(j); - if (!Character.isWhitespace(c2)) { - // If the current character is not the DELIMITER, all whitespace - // characters are significant and should be added to the token. - // Otherwise, they're at the end and should be ignored. But watch - // out for an escape character at the end of the input. Ignore it - // and any previous insignificant whitespace if it exists. - if (c2 == ESCAPE && j + 1 >= values_str.length()) { - continue; - } - if (c2 != DELIMITER) { - buffer.append(values_str.substring(i, j)); - } - // Let loop counter i catch up with the inner loop but keep in - // mind it will still be incremented at the end of the outer loop. - i = j - 1; - break; - } - } - } else { - // For non-whitespace characters. - buffer.append(c1); - } - } - } - // Don't forget to add the last token. - values.add(buffer.toString()); - } - - /* - * Method to return values as Vector. - */ - public Collection getValues() { - return Collections.unmodifiableList(values); - } - - /* - * Method to return values as String[] or null. - */ - public String[] getValuesAsArray() { - if (values.isEmpty()) { - return null; - } - return values.toArray(new String[values.size()]); - } - - public String getValuesAsString() { - if (values.isEmpty()) { - return null; - } - if (values.size() == 1) { - return values.get(0); - } - StringBuffer buffer = new StringBuffer(values.get(0)); - for (int i = 1; i < values.size(); i++) { - buffer.append(','); - buffer.append(values.get(i)); - } - return buffer.toString(); - } - - public String validate(AttributeDefinitionImpl ad) { - // An empty list means the original value was null. Null is never valid. - if (values.isEmpty()) { - return MetaTypeMsg.NULL_IS_INVALID; - } - try { - // A value must match the cardinality. - int cardinality = Math.abs(ad.getCardinality()); - // If the cardinality is zero, the value must contain one and only one token. - if (cardinality == 0) { - if (values.size() != 1) { - return NLS.bind(MetaTypeMsg.CARDINALITY_VIOLATION, new Object[] {getValuesAsString(), values.size(), 1, 1}); - } - } - // Otherwise, the number of tokens must be between 0 and cardinality, inclusive. - else if (values.size() > cardinality) { - return NLS.bind(MetaTypeMsg.CARDINALITY_VIOLATION, new Object[] {getValuesAsString(), values.size(), 0, cardinality}); - } - // Now inspect each token. - for (Iterator i = values.iterator(); i.hasNext();) { - String s = i.next(); - // If options were declared and the value does not match one of them, the value is not valid. - if (!ad._values.isEmpty() && !ad._values.contains(s)) { - return NLS.bind(MetaTypeMsg.VALUE_OUT_OF_OPTION, s); - } - // Check the type. Also check the range if min or max were declared. - boolean rangeError = false; - switch (ad._dataType) { - case AttributeDefinition.PASSWORD : - case AttributeDefinition.STRING : - if (ad._minValue != null && s.length() < (Integer) ad._minValue) { - rangeError = true; - } else if (ad._maxValue != null && s.length() > (Integer) ad._maxValue) { - rangeError = true; - } - break; - case AttributeDefinition.INTEGER : - Integer intVal = new Integer(s); - if (ad._minValue != null && intVal.compareTo((Integer) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && intVal.compareTo((Integer) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.LONG : - Long longVal = new Long(s); - if (ad._minValue != null && longVal.compareTo((Long) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && longVal.compareTo((Long) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.DOUBLE : - Double doubleVal = new Double(s); - if (ad._minValue != null && doubleVal.compareTo((Double) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && doubleVal.compareTo((Double) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.BOOLEAN : - // Any string can be converted into a boolean via Boolean.valueOf(String). - // Seems unnecessary to impose any further restrictions. - break; - case AttributeDefinition.CHARACTER : - Character charVal = new Character(s.charAt(0)); - if (ad._minValue != null && charVal.compareTo((Character) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && charVal.compareTo((Character) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.FLOAT : - Float floatVal = new Float(s); - if (ad._minValue != null && floatVal.compareTo((Float) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && floatVal.compareTo((Float) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.SHORT : - Short shortVal = new Short(s); - if (ad._minValue != null && shortVal.compareTo((Short) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && shortVal.compareTo((Short) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.BYTE : - Byte byteVal = new Byte(s); - if (ad._minValue != null && byteVal.compareTo((Byte) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && byteVal.compareTo((Byte) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.BIGDECIMAL : - BigDecimal bigDecVal = new BigDecimal(s); - if (ad._minValue != null && bigDecVal.compareTo((BigDecimal) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && bigDecVal.compareTo((BigDecimal) ad._maxValue) > 0) { - rangeError = true; - } - break; - case AttributeDefinition.BIGINTEGER : - BigInteger bigIntVal = new BigInteger(s); - if (ad._minValue != null && bigIntVal.compareTo((BigInteger) ad._minValue) < 0) { - rangeError = true; - } else if (ad._maxValue != null && bigIntVal.compareTo((BigInteger) ad._maxValue) > 0) { - rangeError = true; - } - break; - default : - throw new IllegalStateException(); - } - if (rangeError) { - return (NLS.bind(MetaTypeMsg.VALUE_OUT_OF_RANGE, s)); - } - } - // No problems detected - return ""; //$NON-NLS-1$ - } catch (Throwable t) { - String message = NLS.bind(MetaTypeMsg.EXCEPTION_MESSAGE, t.getClass().getName(), t.getMessage()); - logger.log(LogService.LOG_DEBUG, message, t); - return message; - } - } -} +/******************************************************************************* + * Copyright (c) 2005, 2011 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.metatype.impl; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.service.log.LogService; +import org.osgi.service.metatype.AttributeDefinition; + +public class ValueTokenizer { + private static final char DELIMITER = ','; + private static final char ESCAPE = '\\'; + + private final LogService logger; + private final List values = new ArrayList(); + + /* + * Constructor of class ValueTokenizer + */ + public ValueTokenizer(String values_str, LogService logger) { + this.logger = logger; + if (values_str == null) + return; + // The trick is to strip out unescaped whitespace characters before and + // after the input string as well as before and after each + // individual token within the input string without losing any escaped + // whitespace characters. Whitespace between two non-whitespace + // characters may or may not be escaped. Also, any character may be + // escaped. The escape character is '\'. The delimiter is ','. + StringBuffer buffer = new StringBuffer(); + // Loop over the characters within the input string and extract each + // value token. + for (int i = 0; i < values_str.length(); i++) { + char c1 = values_str.charAt(i); + switch (c1) { + case DELIMITER : + // When the delimiter is encountered, add the extracted + // token to the result and prepare the buffer to receive the + // next token. + values.add(buffer.toString()); + buffer.delete(0, buffer.length()); + break; + case ESCAPE : + // When the escape is encountered, add the immediately + // following character to the token, unless the end of the + // input has been reached. Note this will result in loop + // counter 'i' being incremented twice, once here and once + // at the end of the loop. + if (i + 1 < values_str.length()) { + buffer.append(values_str.charAt(++i)); + } else { + // If the ESCAPE character occurs as the last character + // of the string, log the error and ignore it. + logger.log(LogService.LOG_ERROR, "ValueTokenizer.ValueTokenizer(String) " + MetaTypeMsg.TOKENIZER_GOT_INVALID_DATA); //$NON-NLS-1$ + } + break; + default : + // For all other characters, add them to the current token + // unless dealing with unescaped whitespace at the beginning + // or end. We know the whitespace is unescaped because it + // would have been handled in the ESCAPE case otherwise. + if (Character.isWhitespace(c1)) { + // Ignore unescaped whitespace at the beginning of the + // token. + if (buffer.length() == 0) { + continue; + } + // If the whitespace is not at the beginning, look + // forward, starting with the next character, to see if + // it's in the middle or at the end. Unescaped + // whitespace in the middle is okay. + for (int j = i + 1; j < values_str.length(); j++) { + // Keep looping until the end of the string is + // reached or a non-whitespace character other than + // the escape is seen. + char c2 = values_str.charAt(j); + if (!Character.isWhitespace(c2)) { + // If the current character is not the DELIMITER, all whitespace + // characters are significant and should be added to the token. + // Otherwise, they're at the end and should be ignored. But watch + // out for an escape character at the end of the input. Ignore it + // and any previous insignificant whitespace if it exists. + if (c2 == ESCAPE && j + 1 >= values_str.length()) { + continue; + } + if (c2 != DELIMITER) { + buffer.append(values_str.substring(i, j)); + } + // Let loop counter i catch up with the inner loop but keep in + // mind it will still be incremented at the end of the outer loop. + i = j - 1; + break; + } + } + } else { + // For non-whitespace characters. + buffer.append(c1); + } + } + } + // Don't forget to add the last token. + values.add(buffer.toString()); + } + + /* + * Method to return values as Vector. + */ + public Collection getValues() { + return Collections.unmodifiableList(values); + } + + /* + * Method to return values as String[] or null. + */ + public String[] getValuesAsArray() { + if (values.isEmpty()) { + return null; + } + return values.toArray(new String[values.size()]); + } + + public String getValuesAsString() { + if (values.isEmpty()) { + return null; + } + if (values.size() == 1) { + return values.get(0); + } + StringBuffer buffer = new StringBuffer(values.get(0)); + for (int i = 1; i < values.size(); i++) { + buffer.append(','); + buffer.append(values.get(i)); + } + return buffer.toString(); + } + + public String validate(AttributeDefinitionImpl ad) { + // An empty list means the original value was null. Null is never valid. + if (values.isEmpty()) { + return MetaTypeMsg.NULL_IS_INVALID; + } + try { + // A value must match the cardinality. + int cardinality = Math.abs(ad.getCardinality()); + // If the cardinality is zero, the value must contain one and only one token. + if (cardinality == 0) { + if (values.size() != 1) { + return NLS.bind(MetaTypeMsg.CARDINALITY_VIOLATION, new Object[] {getValuesAsString(), values.size(), 1, 1}); + } + } + // Otherwise, the number of tokens must be between 0 and cardinality, inclusive. + else if (values.size() > cardinality) { + return NLS.bind(MetaTypeMsg.CARDINALITY_VIOLATION, new Object[] {getValuesAsString(), values.size(), 0, cardinality}); + } + // Now inspect each token. + for (Iterator i = values.iterator(); i.hasNext();) { + String s = i.next(); + // If options were declared and the value does not match one of them, the value is not valid. + if (!ad._values.isEmpty() && !ad._values.contains(s)) { + return NLS.bind(MetaTypeMsg.VALUE_OUT_OF_OPTION, s); + } + // Check the type. Also check the range if min or max were declared. + boolean rangeError = false; + switch (ad._dataType) { + case AttributeDefinition.PASSWORD : + case AttributeDefinition.STRING : + if (ad._minValue != null && s.length() < (Integer) ad._minValue) { + rangeError = true; + } else if (ad._maxValue != null && s.length() > (Integer) ad._maxValue) { + rangeError = true; + } + break; + case AttributeDefinition.INTEGER : + Integer intVal = new Integer(s); + if (ad._minValue != null && intVal.compareTo((Integer) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && intVal.compareTo((Integer) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.LONG : + Long longVal = new Long(s); + if (ad._minValue != null && longVal.compareTo((Long) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && longVal.compareTo((Long) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.DOUBLE : + Double doubleVal = new Double(s); + if (ad._minValue != null && doubleVal.compareTo((Double) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && doubleVal.compareTo((Double) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.BOOLEAN : + // Any string can be converted into a boolean via Boolean.valueOf(String). + // Seems unnecessary to impose any further restrictions. + break; + case AttributeDefinition.CHARACTER : + Character charVal = new Character(s.charAt(0)); + if (ad._minValue != null && charVal.compareTo((Character) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && charVal.compareTo((Character) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.FLOAT : + Float floatVal = new Float(s); + if (ad._minValue != null && floatVal.compareTo((Float) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && floatVal.compareTo((Float) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.SHORT : + Short shortVal = new Short(s); + if (ad._minValue != null && shortVal.compareTo((Short) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && shortVal.compareTo((Short) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.BYTE : + Byte byteVal = new Byte(s); + if (ad._minValue != null && byteVal.compareTo((Byte) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && byteVal.compareTo((Byte) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.BIGDECIMAL : + BigDecimal bigDecVal = new BigDecimal(s); + if (ad._minValue != null && bigDecVal.compareTo((BigDecimal) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && bigDecVal.compareTo((BigDecimal) ad._maxValue) > 0) { + rangeError = true; + } + break; + case AttributeDefinition.BIGINTEGER : + BigInteger bigIntVal = new BigInteger(s); + if (ad._minValue != null && bigIntVal.compareTo((BigInteger) ad._minValue) < 0) { + rangeError = true; + } else if (ad._maxValue != null && bigIntVal.compareTo((BigInteger) ad._maxValue) > 0) { + rangeError = true; + } + break; + default : + throw new IllegalStateException(); + } + if (rangeError) { + return (NLS.bind(MetaTypeMsg.VALUE_OUT_OF_RANGE, s)); + } + } + // No problems detected + return ""; //$NON-NLS-1$ + } catch (Throwable t) { + String message = NLS.bind(MetaTypeMsg.EXCEPTION_MESSAGE, t.getClass().getName(), t.getMessage()); + logger.log(LogService.LOG_DEBUG, message, t); + return message; + } + } +} diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/EclipsePreferences.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/EclipsePreferences.java index f419200b2..578a21b43 100644 --- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/EclipsePreferences.java +++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/EclipsePreferences.java @@ -1,1238 +1,1238 @@ -/******************************************************************************* - * Copyright (c) 2004, 2011 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 - * Julian Chen - fix for bug #92572, jclRM - *******************************************************************************/ -package org.eclipse.core.internal.preferences; - -import java.io.*; -import java.util.*; -import org.eclipse.core.internal.runtime.RuntimeLog; -import org.eclipse.core.runtime.*; -import org.eclipse.core.runtime.preferences.*; -import org.eclipse.osgi.util.NLS; -import org.osgi.service.prefs.BackingStoreException; -import org.osgi.service.prefs.Preferences; - -/** - * Represents a node in the Eclipse preference node hierarchy. This class - * is used as a default implementation/super class for those nodes which - * belong to scopes which are contributed by the Platform. - * - * Implementation notes: - * - * - For thread safety, we always synchronize on the node object when writing - * the children or properties fields. Must ensure we don't synchronize when calling - * client code such as listeners. - * - * @since 3.0 - */ -public class EclipsePreferences implements IEclipsePreferences, IScope { - - public static final String DEFAULT_PREFERENCES_DIRNAME = ".settings"; //$NON-NLS-1$ - public static final String PREFS_FILE_EXTENSION = "prefs"; //$NON-NLS-1$ - protected static final IEclipsePreferences[] EMPTY_NODE_ARRAY = new IEclipsePreferences[0]; - protected static final String[] EMPTY_STRING_ARRAY = new String[0]; - private static final String FALSE = "false"; //$NON-NLS-1$ - private static final String TRUE = "true"; //$NON-NLS-1$ - protected static final String VERSION_KEY = "eclipse.preferences.version"; //$NON-NLS-1$ - protected static final String VERSION_VALUE = "1"; //$NON-NLS-1$ - protected static final String PATH_SEPARATOR = String.valueOf(IPath.SEPARATOR); - protected static final String DOUBLE_SLASH = "//"; //$NON-NLS-1$ - protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ - - private String cachedPath; - protected Map children; - protected boolean dirty = false; - protected boolean loading = false; - protected final String name; - // the parent of an EclipsePreference node is always an EclipsePreference node. (or null) - protected final EclipsePreferences parent; - protected ImmutableMap properties = ImmutableMap.EMPTY; - protected boolean removed = false; - private ListenerList nodeChangeListeners; - private ListenerList preferenceChangeListeners; - - public static boolean DEBUG_PREFERENCE_GENERAL = false; - public static boolean DEBUG_PREFERENCE_SET = false; - public static boolean DEBUG_PREFERENCE_GET = false; - - protected final static String debugPluginName = "org.eclipse.equinox.preferences"; //$NON-NLS-1$ - - static { - DEBUG_PREFERENCE_GENERAL = PreferencesOSGiUtils.getDefault().getBooleanDebugOption(debugPluginName + "/general", false); //$NON-NLS-1$ - DEBUG_PREFERENCE_SET = PreferencesOSGiUtils.getDefault().getBooleanDebugOption(debugPluginName + "/set", false); //$NON-NLS-1$ - DEBUG_PREFERENCE_GET = PreferencesOSGiUtils.getDefault().getBooleanDebugOption(debugPluginName + "/get", false); //$NON-NLS-1$ - } - - protected class SortedProperties extends Properties { - - private static final long serialVersionUID = 1L; - - public SortedProperties() { - super(); - } - - /* (non-Javadoc) - * @see java.util.Hashtable#keys() - */ - public synchronized Enumeration keys() { - TreeSet set = new TreeSet(); - for (Enumeration e = super.keys(); e.hasMoreElements();) - set.add(e.nextElement()); - return Collections.enumeration(set); - } - - /* (non-Javadoc) - * @see java.util.Hashtable#entrySet() - */ - public Set entrySet() { - TreeSet set = new TreeSet(new Comparator() { - public int compare(Object e1, Object e2) { - String s1 = (String) ((Map.Entry) e1).getKey(); - String s2 = (String) ((Map.Entry) e2).getKey(); - return s1.compareTo(s2); - } - }); - for (Iterator i = super.entrySet().iterator(); i.hasNext();) - set.add(i.next()); - return set; - } - } - - public EclipsePreferences() { - this(null, null); - } - - protected EclipsePreferences(EclipsePreferences parent, String name) { - super(); - this.parent = parent; - this.name = name; - this.cachedPath = null; // make sure the cached path is cleared after setting the parent - } - - /* - * @see org.osgi.service.prefs.Preferences#absolutePath() - */ - public String absolutePath() { - if (cachedPath == null) { - if (parent == null) - cachedPath = PATH_SEPARATOR; - else { - String parentPath = parent.absolutePath(); - // if the parent is the root then we don't have to add a separator - // between the parent path and our path - if (parentPath.length() == 1) - cachedPath = parentPath + name(); - else - cachedPath = parentPath + PATH_SEPARATOR + name(); - } - } - return cachedPath; - } - - public void accept(IPreferenceNodeVisitor visitor) throws BackingStoreException { - if (!visitor.visit(this)) - return; - IEclipsePreferences[] toVisit = getChildren(true); - for (int i = 0; i < toVisit.length; i++) - toVisit[i].accept(visitor); - } - - protected synchronized IEclipsePreferences addChild(String childName, IEclipsePreferences child) { - //Thread safety: synchronize method to protect modification of children field - if (children == null) - children = Collections.synchronizedMap(new HashMap()); - children.put(childName, child == null ? (Object) childName : child); - return child; - } - - /* - * @see org.eclipse.core.runtime.IEclipsePreferences#addNodeChangeListener(org.eclipse.core.runtime.IEclipsePreferences.INodeChangeListener) - */ - public void addNodeChangeListener(INodeChangeListener listener) { - checkRemoved(); - if (nodeChangeListeners == null) - nodeChangeListeners = new ListenerList(); - nodeChangeListeners.add(listener); - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Added preference node change listener: " + listener + " to: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ - } - - /* - * @see org.eclipse.core.runtime.IEclipsePreferences#addPreferenceChangeListener(org.eclipse.core.runtime.IEclipsePreferences.IPreferenceChangeListener) - */ - public void addPreferenceChangeListener(IPreferenceChangeListener listener) { - checkRemoved(); - if (preferenceChangeListeners == null) - preferenceChangeListeners = new ListenerList(); - preferenceChangeListeners.add(listener); - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Added preference property change listener: " + listener + " to: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ - } - - private IEclipsePreferences calculateRoot() { - IEclipsePreferences result = this; - while (result.parent() != null) - result = (IEclipsePreferences) result.parent(); - return result; - } - - /* - * Convenience method for throwing an exception when methods - * are called on a removed node. - */ - protected void checkRemoved() { - if (removed) - throw new IllegalStateException(NLS.bind(PrefsMessages.preferences_removedNode, name)); - } - - /* - * @see org.osgi.service.prefs.Preferences#childrenNames() - */ - public String[] childrenNames() { - // illegal state if this node has been removed - checkRemoved(); - return internalChildNames(); - } - - protected String[] internalChildNames() { - Map temp = children; - if (temp == null || temp.size() == 0) - return EMPTY_STRING_ARRAY; - return (String[]) temp.keySet().toArray(EMPTY_STRING_ARRAY); - } - - /* - * @see org.osgi.service.prefs.Preferences#clear() - */ - public void clear() { - // illegal state if this node has been removed - checkRemoved(); - // call each one separately (instead of Properties.clear) so - // clients get change notification - String[] keys = properties.keys(); - for (int i = 0; i < keys.length; i++) - remove(keys[i]); - makeDirty(); - } - - protected String[] computeChildren(IPath root) { - if (root == null) - return EMPTY_STRING_ARRAY; - IPath dir = root.append(DEFAULT_PREFERENCES_DIRNAME); - final ArrayList result = new ArrayList(); - final String extension = '.' + PREFS_FILE_EXTENSION; - File file = dir.toFile(); - File[] totalFiles = file.listFiles(); - if (totalFiles != null) { - for (int i = 0; i < totalFiles.length; i++) { - if (totalFiles[i].isFile()) { - String filename = totalFiles[i].getName(); - if (filename.endsWith(extension)) { - String shortName = filename.substring(0, filename.length() - extension.length()); - result.add(shortName); - } - } - } - } - return (String[]) result.toArray(EMPTY_STRING_ARRAY); - } - - protected IPath computeLocation(IPath root, String qualifier) { - return root == null ? null : root.append(DEFAULT_PREFERENCES_DIRNAME).append(qualifier).addFileExtension(PREFS_FILE_EXTENSION); - } - - /* - * Version 1 (current version) - * path/key=value - */ - protected static void convertFromProperties(EclipsePreferences node, Properties table, boolean notify) { - String version = table.getProperty(VERSION_KEY); - if (version == null || !VERSION_VALUE.equals(version)) { - // ignore for now - } - table.remove(VERSION_KEY); - for (Iterator i = table.keySet().iterator(); i.hasNext();) { - String fullKey = (String) i.next(); - String value = table.getProperty(fullKey); - if (value != null) { - String[] splitPath = decodePath(fullKey); - String path = splitPath[0]; - path = makeRelative(path); - String key = splitPath[1]; - if (DEBUG_PREFERENCE_SET) - PrefsMessages.message("Setting preference: " + path + '/' + key + '=' + value); //$NON-NLS-1$ - //use internal methods to avoid notifying listeners - EclipsePreferences childNode = (EclipsePreferences) node.internalNode(path, false, null); - String oldValue = childNode.internalPut(key, value); - // notify listeners if applicable - if (notify && !value.equals(oldValue)) - childNode.firePreferenceEvent(key, oldValue, value); - } - } - PreferencesService.getDefault().shareStrings(); - } - - /* - * Helper method to persist a Properties object to the filesystem. We use this - * helper so we can remove the date/timestamp that Properties#store always - * puts in the file. - */ - protected static void write(Properties properties, IPath location) throws BackingStoreException { - // create the parent dirs if they don't exist - File parentFile = location.toFile().getParentFile(); - if (parentFile == null) - return; - parentFile.mkdirs(); - - OutputStream output = null; - try { - output = new BufferedOutputStream(new FileOutputStream(new File(location.toOSString()))); - output.write(removeTimestampFromTable(properties).getBytes("UTF-8")); //$NON-NLS-1$ - output.flush(); - } catch (IOException e) { - String message = NLS.bind(PrefsMessages.preferences_saveException, location); - log(new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e)); - throw new BackingStoreException(message); - } finally { - if (output != null) - try { - output.close(); - } catch (IOException e) { - // ignore - } - } - } - - protected static String removeTimestampFromTable(Properties properties) throws IOException { - // store the properties in a string and then skip the first line (date/timestamp) - ByteArrayOutputStream output = new ByteArrayOutputStream(); - try { - properties.store(output, null); - } finally { - output.close(); - } - String string = output.toString("UTF-8"); //$NON-NLS-1$ - String separator = System.getProperty("line.separator"); //$NON-NLS-1$ - return string.substring(string.indexOf(separator) + separator.length()); - } - - /* - * Helper method to convert this node to a Properties file suitable - * for persistence. - */ - protected Properties convertToProperties(Properties result, String prefix) throws BackingStoreException { - // add the key/value pairs from this node - boolean addSeparator = prefix.length() != 0; - //thread safety: copy reference in case of concurrent change - ImmutableMap temp = properties; - String[] keys = temp.keys(); - for (int i = 0, imax = keys.length; i < imax; i++) { - String value = temp.get(keys[i]); - if (value != null) - result.put(encodePath(prefix, keys[i]), value); - } - // recursively add the child information - IEclipsePreferences[] childNodes = getChildren(true); - for (int i = 0; i < childNodes.length; i++) { - EclipsePreferences child = (EclipsePreferences) childNodes[i]; - String fullPath = addSeparator ? prefix + PATH_SEPARATOR + child.name() : child.name(); - child.convertToProperties(result, fullPath); - } - PreferencesService.getDefault().shareStrings(); - return result; - } - - /* - * @see org.eclipse.core.runtime.preferences.IScope#create(org.eclipse.core.runtime.preferences.IEclipsePreferences) - */ - public IEclipsePreferences create(IEclipsePreferences nodeParent, String nodeName) { - return create((EclipsePreferences) nodeParent, nodeName, null); - } - - protected boolean isLoading() { - return loading; - } - - protected void setLoading(boolean isLoading) { - loading = isLoading; - } - - public IEclipsePreferences create(EclipsePreferences nodeParent, String nodeName, Object context) { - EclipsePreferences result = internalCreate(nodeParent, nodeName, context); - nodeParent.addChild(nodeName, result); - IEclipsePreferences loadLevel = result.getLoadLevel(); - - // if this node or a parent node is not the load level then return - if (loadLevel == null) - return result; - - // if the result node is not a load level, then a child must be - if (result != loadLevel) - return result; - - // the result node is a load level - if (isAlreadyLoaded(result) || result.isLoading()) - return result; - try { - result.setLoading(true); - result.loadLegacy(); - result.load(); - result.loaded(); - result.flush(); - } catch (BackingStoreException e) { - IPath location = result.getLocation(); - String message = NLS.bind(PrefsMessages.preferences_loadException, location == null ? EMPTY_STRING : location.toString()); - IStatus status = new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e); - RuntimeLog.log(status); - } finally { - result.setLoading(false); - } - return result; - } - - /* - * @see org.osgi.service.prefs.Preferences#flush() - */ - synchronized public void flush() throws BackingStoreException { - // illegal state if this node has been removed - checkRemoved(); - - IEclipsePreferences loadLevel = getLoadLevel(); - - // if this node or a parent is not the load level, then flush the children - if (loadLevel == null) { - String[] childrenNames = childrenNames(); - for (int i = 0; i < childrenNames.length; i++) - node(childrenNames[i]).flush(); - return; - } - - // a parent is the load level for this node - if (this != loadLevel) { - loadLevel.flush(); - return; - } - - // this node is a load level - // any work to do? - if (!dirty) - return; - //remove dirty bit before saving, to ensure that concurrent - //changes during save mark the store as dirty - dirty = false; - try { - save(); - } catch (BackingStoreException e) { - //mark it dirty again because the save failed - dirty = true; - throw e; - } - } - - /* - * @see org.osgi.service.prefs.Preferences#get(java.lang.String, java.lang.String) - */ - public String get(String key, String defaultValue) { - String value = internalGet(key); - return value == null ? defaultValue : value; - } - - /* - * @see org.osgi.service.prefs.Preferences#getBoolean(java.lang.String, boolean) - */ - public boolean getBoolean(String key, boolean defaultValue) { - String value = internalGet(key); - return value == null ? defaultValue : TRUE.equalsIgnoreCase(value); - } - - /* - * @see org.osgi.service.prefs.Preferences#getByteArray(java.lang.String, byte[]) - */ - public byte[] getByteArray(String key, byte[] defaultValue) { - String value = internalGet(key); - return value == null ? defaultValue : Base64.decode(value.getBytes()); - } - - /* - * Return a boolean value indicating whether or not a child with the given - * name is known to this node. - */ - protected synchronized boolean childExists(String childName) { - if (children == null) - return false; - return children.get(childName) != null; - } - - /** - * Thread safe way to obtain a child for a given key. Returns the child - * that matches the given key, or null if there is no matching child. - */ - protected IEclipsePreferences getChild(String key, Object context, boolean create) { - synchronized (this) { - if (children == null) - return null; - Object value = children.get(key); - if (value == null) - return null; - if (value instanceof IEclipsePreferences) - return (IEclipsePreferences) value; - // if we aren't supposed to create this node, then - // just return null - if (!create) - return null; - } - return addChild(key, create(this, key, context)); - } - - /** - * Thread safe way to obtain all children of this node. Never returns null. - */ - protected IEclipsePreferences[] getChildren(boolean create) { - ArrayList result = new ArrayList(); - String[] names = internalChildNames(); - for (int i = 0; i < names.length; i++) { - IEclipsePreferences child = getChild(names[i], null, create); - if (child != null) - result.add(child); - } - return (IEclipsePreferences[]) result.toArray(EMPTY_NODE_ARRAY); - } - - /* - * @see org.osgi.service.prefs.Preferences#getDouble(java.lang.String, double) - */ - public double getDouble(String key, double defaultValue) { - String value = internalGet(key); - double result = defaultValue; - if (value != null) - try { - result = Double.parseDouble(value); - } catch (NumberFormatException e) { - // use default - } - return result; - } - - /* - * @see org.osgi.service.prefs.Preferences#getFloat(java.lang.String, float) - */ - public float getFloat(String key, float defaultValue) { - String value = internalGet(key); - float result = defaultValue; - if (value != null) - try { - result = Float.parseFloat(value); - } catch (NumberFormatException e) { - // use default - } - return result; - } - - /* - * @see org.osgi.service.prefs.Preferences#getInt(java.lang.String, int) - */ - public int getInt(String key, int defaultValue) { - String value = internalGet(key); - int result = defaultValue; - if (value != null) - try { - result = Integer.parseInt(value); - } catch (NumberFormatException e) { - // use default - } - return result; - } - - protected IEclipsePreferences getLoadLevel() { - return null; - } - - /* - * Subclasses to over-ride - */ - protected IPath getLocation() { - return null; - } - - /* - * @see org.osgi.service.prefs.Preferences#getLong(java.lang.String, long) - */ - public long getLong(String key, long defaultValue) { - String value = internalGet(key); - long result = defaultValue; - if (value != null) - try { - result = Long.parseLong(value); - } catch (NumberFormatException e) { - // use default - } - return result; - } - - protected EclipsePreferences internalCreate(EclipsePreferences nodeParent, String nodeName, Object context) { - return new EclipsePreferences(nodeParent, nodeName); - } - - /** - * Returns the existing value at the given key, or null if - * no such value exists. - */ - protected String internalGet(String key) { - // throw NPE if key is null - if (key == null) - throw new NullPointerException(); - // illegal state if this node has been removed - checkRemoved(); - String result = properties.get(key); - if (DEBUG_PREFERENCE_GET) - PrefsMessages.message("Getting preference value: " + absolutePath() + '/' + key + "->" + result); //$NON-NLS-1$ //$NON-NLS-2$ - return result; - } - - /** - * Implements the node(String) method, and optionally notifies listeners. - */ - protected IEclipsePreferences internalNode(String path, boolean notify, Object context) { - - // illegal state if this node has been removed - checkRemoved(); - - // short circuit this node - if (path.length() == 0) - return this; - - // if we have an absolute path use the root relative to - // this node instead of the global root - // in case we have a different hierarchy. (e.g. export) - if (path.charAt(0) == IPath.SEPARATOR) - return (IEclipsePreferences) calculateRoot().node(path.substring(1)); - - int index = path.indexOf(IPath.SEPARATOR); - String key = index == -1 ? path : path.substring(0, index); - boolean added = false; - IEclipsePreferences child = getChild(key, context, true); - if (child == null) { - child = create(this, key, context); - added = true; - } - // notify listeners if a child was added - if (added && notify) - fireNodeEvent(new NodeChangeEvent(this, child), true); - return (IEclipsePreferences) child.node(index == -1 ? EMPTY_STRING : path.substring(index + 1)); - } - - /** - * Stores the given (key,value) pair, performing lazy initialization of the - * properties field if necessary. Returns the old value for the given key, - * or null if no value existed. - */ - protected String internalPut(String key, String newValue) { - // illegal state if this node has been removed - checkRemoved(); - String oldValue = properties.get(key); - if (oldValue != null && oldValue.equals(newValue)) - return oldValue; - if (DEBUG_PREFERENCE_SET) - PrefsMessages.message("Setting preference: " + absolutePath() + '/' + key + '=' + newValue); //$NON-NLS-1$ - properties = properties.put(key, newValue); - return oldValue; - } - - /* - * Subclasses to over-ride. - */ - protected boolean isAlreadyLoaded(IEclipsePreferences node) { - return true; - } - - /* - * @see org.osgi.service.prefs.Preferences#keys() - */ - public String[] keys() { - // illegal state if this node has been removed - checkRemoved(); - return properties.keys(); - } - - /** - * Loads the preference node. This method returns silently if the node does not exist - * in the backing store (for example non-existent project). - * - * @throws BackingStoreException if the node exists in the backing store but it - * could not be loaded - */ - protected void load() throws BackingStoreException { - load(getLocation()); - } - - protected static Properties loadProperties(IPath location) throws BackingStoreException { - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Loading preferences from file: " + location); //$NON-NLS-1$ - InputStream input = null; - Properties result = new Properties(); - try { - input = new BufferedInputStream(new FileInputStream(location.toFile())); - result.load(input); - } catch (FileNotFoundException e) { - // file doesn't exist but that's ok. - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Preference file does not exist: " + location); //$NON-NLS-1$ - return result; - } catch (IOException e) { - String message = NLS.bind(PrefsMessages.preferences_loadException, location); - log(new Status(IStatus.INFO, PrefsMessages.OWNER_NAME, IStatus.INFO, message, e)); - throw new BackingStoreException(message); - } finally { - if (input != null) - try { - input.close(); - } catch (IOException e) { - // ignore - } - } - return result; - } - - protected void load(IPath location) throws BackingStoreException { - if (location == null) { - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Unable to determine location of preference file for node: " + absolutePath()); //$NON-NLS-1$ - return; - } - Properties fromDisk = loadProperties(location); - convertFromProperties(this, fromDisk, false); - } - - protected void loaded() { - // do nothing - } - - protected void loadLegacy() { - // sub-classes to over-ride if necessary - } - - public static void log(IStatus status) { - RuntimeLog.log(status); - } - - protected void makeDirty() { - EclipsePreferences node = this; - while (node != null && !node.removed) { - node.dirty = true; - node = (EclipsePreferences) node.parent(); - } - } - - public boolean isDirty() { - return dirty; - } - - /* - * @see org.osgi.service.prefs.Preferences#name() - */ - public String name() { - return name; - } - - /* - * @see org.osgi.service.prefs.Preferences#node(java.lang.String) - */ - public Preferences node(String pathName) { - return internalNode(pathName, true, null); - } - - protected void fireNodeEvent(final NodeChangeEvent event, final boolean added) { - if (nodeChangeListeners == null) - return; - Object[] listeners = nodeChangeListeners.getListeners(); - for (int i = 0; i < listeners.length; i++) { - final INodeChangeListener listener = (INodeChangeListener) listeners[i]; - ISafeRunnable job = new ISafeRunnable() { - public void handleException(Throwable exception) { - // already logged in Platform#run() - } - - public void run() throws Exception { - if (added) - listener.added(event); - else - listener.removed(event); - } - }; - SafeRunner.run(job); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#nodeExists(java.lang.String) - */ - public boolean nodeExists(String path) throws BackingStoreException { - // short circuit for checking this node - if (path.length() == 0) - return !removed; - - // illegal state if this node has been removed. - // do this AFTER checking for the empty string. - checkRemoved(); - - // use the root relative to this node instead of the global root - // in case we have a different hierarchy. (e.g. export) - if (path.charAt(0) == IPath.SEPARATOR) - return calculateRoot().nodeExists(path.substring(1)); - - int index = path.indexOf(IPath.SEPARATOR); - boolean noSlash = index == -1; - - // if we are looking for a simple child then just look in the table and return - if (noSlash) - return childExists(path); - - // otherwise load the parent of the child and then recursively ask - String childName = path.substring(0, index); - if (!childExists(childName)) - return false; - IEclipsePreferences child = getChild(childName, null, true); - if (child == null) - return false; - return child.nodeExists(path.substring(index + 1)); - } - - /* - * @see org.osgi.service.prefs.Preferences#parent() - */ - public Preferences parent() { - // illegal state if this node has been removed - checkRemoved(); - return parent; - } - - /* - * Convenience method for notifying preference change listeners. - */ - protected void firePreferenceEvent(String key, Object oldValue, Object newValue) { - if (preferenceChangeListeners == null) - return; - Object[] listeners = preferenceChangeListeners.getListeners(); - final PreferenceChangeEvent event = new PreferenceChangeEvent(this, key, oldValue, newValue); - for (int i = 0; i < listeners.length; i++) { - final IPreferenceChangeListener listener = (IPreferenceChangeListener) listeners[i]; - ISafeRunnable job = new ISafeRunnable() { - public void handleException(Throwable exception) { - // already logged in Platform#run() - } - - public void run() throws Exception { - listener.preferenceChange(event); - } - }; - SafeRunner.run(job); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#put(java.lang.String, java.lang.String) - */ - public void put(String key, String newValue) { - if (key == null || newValue == null) - throw new NullPointerException(); - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#putBoolean(java.lang.String, boolean) - */ - public void putBoolean(String key, boolean value) { - if (key == null) - throw new NullPointerException(); - String newValue = value ? TRUE : FALSE; - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#putByteArray(java.lang.String, byte[]) - */ - public void putByteArray(String key, byte[] value) { - if (key == null || value == null) - throw new NullPointerException(); - String newValue = new String(Base64.encode(value)); - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#putDouble(java.lang.String, double) - */ - public void putDouble(String key, double value) { - if (key == null) - throw new NullPointerException(); - String newValue = Double.toString(value); - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#putFloat(java.lang.String, float) - */ - public void putFloat(String key, float value) { - if (key == null) - throw new NullPointerException(); - String newValue = Float.toString(value); - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#putInt(java.lang.String, int) - */ - public void putInt(String key, int value) { - if (key == null) - throw new NullPointerException(); - String newValue = Integer.toString(value); - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#putLong(java.lang.String, long) - */ - public void putLong(String key, long value) { - if (key == null) - throw new NullPointerException(); - String newValue = Long.toString(value); - String oldValue = internalPut(key, newValue); - if (!newValue.equals(oldValue)) { - makeDirty(); - firePreferenceEvent(key, oldValue, newValue); - } - } - - /* - * @see org.osgi.service.prefs.Preferences#remove(java.lang.String) - */ - public void remove(String key) { - // illegal state if this node has been removed - checkRemoved(); - String oldValue = properties.get(key); - if (oldValue == null) - return; - properties = properties.removeKey(key); - makeDirty(); - firePreferenceEvent(key, oldValue, null); - } - - /* - * @see org.osgi.service.prefs.Preferences#removeNode() - */ - public void removeNode() throws BackingStoreException { - // illegal state if this node has been removed - checkRemoved(); - // clear all the property values. do it "the long way" so - // everyone gets notification - String[] keys = keys(); - for (int i = 0; i < keys.length; i++) - remove(keys[i]); - // don't remove the global root or the scope root from the - // parent but remove all its children - if (parent != null && !(parent instanceof RootPreferences)) { - // remove the node from the parent's collection and notify listeners - removed = true; - parent.removeNode(this); - } - IEclipsePreferences[] childNodes = getChildren(false); - for (int i = 0; i < childNodes.length; i++) - try { - childNodes[i].removeNode(); - } catch (IllegalStateException e) { - // ignore since we only get this exception if we have already - // been removed. no work to do. - } - } - - /* - * Remove the child from the collection and notify the listeners if something - * was actually removed. - */ - protected void removeNode(IEclipsePreferences child) { - boolean wasRemoved = false; - synchronized (this) { - if (children != null) { - wasRemoved = children.remove(child.name()) != null; - if (wasRemoved) - makeDirty(); - if (children.isEmpty()) - children = null; - } - } - if (wasRemoved) - fireNodeEvent(new NodeChangeEvent(this, child), false); - } - - /* - * Remove non-initialized node from the collection. - */ - protected void removeNode(String key) { - synchronized (this) { - if (children != null) { - boolean wasRemoved = children.remove(key) != null; - if (wasRemoved) - makeDirty(); - if (children.isEmpty()) - children = null; - } - } - } - - /* - * @see org.eclipse.core.runtime.IEclipsePreferences#removeNodeChangeListener(org.eclipse.core.runtime.IEclipsePreferences.removeNodeChangeListener) - */ - public void removeNodeChangeListener(INodeChangeListener listener) { - checkRemoved(); - if (nodeChangeListeners == null) - return; - nodeChangeListeners.remove(listener); - if (nodeChangeListeners.size() == 0) - nodeChangeListeners = null; - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Removed preference node change listener: " + listener + " from: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ - } - - /* - * @see org.eclipse.core.runtime.IEclipsePreferences#removePreferenceChangeListener(org.eclipse.core.runtime.IEclipsePreferences.IPreferenceChangeListener) - */ - public void removePreferenceChangeListener(IPreferenceChangeListener listener) { - checkRemoved(); - if (preferenceChangeListeners == null) - return; - preferenceChangeListeners.remove(listener); - if (preferenceChangeListeners.size() == 0) - preferenceChangeListeners = null; - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Removed preference property change listener: " + listener + " from: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ - } - - /** - * Saves the preference node. This method returns silently if the node does not exist - * in the backing store (for example non-existent project) - * - * @throws BackingStoreException if the node exists in the backing store but it - * could not be saved - */ - protected void save() throws BackingStoreException { - save(getLocation()); - } - - protected void save(IPath location) throws BackingStoreException { - if (location == null) { - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Unable to determine location of preference file for node: " + absolutePath()); //$NON-NLS-1$ - return; - } - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Saving preferences to file: " + location); //$NON-NLS-1$ - Properties table = convertToProperties(new SortedProperties(), EMPTY_STRING); - if (table.isEmpty()) { - // nothing to save. delete existing file if one exists. - if (location.toFile().exists() && !location.toFile().delete()) { - String message = NLS.bind(PrefsMessages.preferences_failedDelete, location); - log(new Status(IStatus.WARNING, PrefsMessages.OWNER_NAME, IStatus.WARNING, message, null)); - } - return; - } - table.put(VERSION_KEY, VERSION_VALUE); - write(table, location); - } - - /** - * Traverses the preference hierarchy rooted at this node, and adds - * all preference key and value strings to the provided pool. If an added - * string was already in the pool, all references will be replaced with the - * canonical copy of the string. - * - * @param pool The pool to share strings in - */ - public void shareStrings(StringPool pool) { - properties.shareStrings(pool); - IEclipsePreferences[] myChildren = getChildren(false); - for (int i = 0; i < myChildren.length; i++) - if (myChildren[i] instanceof EclipsePreferences) - ((EclipsePreferences) myChildren[i]).shareStrings(pool); - } - - /* - * Encode the given path and key combo to a form which is suitable for - * persisting or using when searching. If the key contains a slash character - * then we must use a double-slash to indicate the end of the - * path/the beginning of the key. - */ - public static String encodePath(String path, String key) { - String result; - int pathLength = path == null ? 0 : path.length(); - if (key.indexOf(IPath.SEPARATOR) == -1) { - if (pathLength == 0) - result = key; - else - result = path + IPath.SEPARATOR + key; - } else { - if (pathLength == 0) - result = DOUBLE_SLASH + key; - else - result = path + DOUBLE_SLASH + key; - } - return result; - } - - /* - * Return the segment from the given path or null. - * "segment" parameter is 0-based. - */ - public static String getSegment(String path, int segment) { - int start = path.indexOf(IPath.SEPARATOR) == 0 ? 1 : 0; - int end = path.indexOf(IPath.SEPARATOR, start); - if (end == path.length() - 1) - end = -1; - for (int i = 0; i < segment; i++) { - if (end == -1) - return null; - start = end + 1; - end = path.indexOf(IPath.SEPARATOR, start); - } - if (end == -1) - end = path.length(); - return path.substring(start, end); - } - - public static int getSegmentCount(String path) { - StringTokenizer tokenizer = new StringTokenizer(path, String.valueOf(IPath.SEPARATOR)); - return tokenizer.countTokens(); - } - - /* - * Return a relative path - */ - public static String makeRelative(String path) { - String result = path; - if (path == null) - return EMPTY_STRING; - if (path.length() > 0 && path.charAt(0) == IPath.SEPARATOR) - result = path.length() == 0 ? EMPTY_STRING : path.substring(1); - return result; - } - - /* - * Return a 2 element String array. - * element 0 - the path - * element 1 - the key - * The path may be null. - * The key is never null. - */ - public static String[] decodePath(String fullPath) { - String key = null; - String path = null; - - // check to see if we have an indicator which tells us where the path ends - int index = fullPath.indexOf(DOUBLE_SLASH); - if (index == -1) { - // we don't have a double-slash telling us where the path ends - // so the path is up to the last slash character - int lastIndex = fullPath.lastIndexOf(IPath.SEPARATOR); - if (lastIndex == -1) { - key = fullPath; - } else { - path = fullPath.substring(0, lastIndex); - key = fullPath.substring(lastIndex + 1); - } - } else { - // the child path is up to the double-slash and the key - // is the string after it - path = fullPath.substring(0, index); - key = fullPath.substring(index + 2); - } - - // adjust if we have an absolute path - if (path != null) - if (path.length() == 0) - path = null; - else if (path.charAt(0) == IPath.SEPARATOR) - path = path.substring(1); - - return new String[] {path, key}; - } - - /* - * @see org.osgi.service.prefs.Preferences#sync() - */ - - public void sync() throws BackingStoreException { - // illegal state if this node has been removed - checkRemoved(); - IEclipsePreferences node = getLoadLevel(); - if (node == null) { - if (DEBUG_PREFERENCE_GENERAL) - PrefsMessages.message("Preference node is not a load root: " + absolutePath()); //$NON-NLS-1$ - return; - } - if (node instanceof EclipsePreferences) { - ((EclipsePreferences) node).load(); - node.flush(); - } - } - - public String toDeepDebugString() { - final StringBuffer buffer = new StringBuffer(); - IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() { - public boolean visit(IEclipsePreferences node) throws BackingStoreException { - buffer.append(node); - buffer.append('\n'); - String[] keys = node.keys(); - for (int i = 0; i < keys.length; i++) { - buffer.append(node.absolutePath()); - buffer.append(PATH_SEPARATOR); - buffer.append(keys[i]); - buffer.append('='); - buffer.append(node.get(keys[i], "*default*")); //$NON-NLS-1$ - buffer.append('\n'); - } - return true; - } - }; - try { - accept(visitor); - } catch (BackingStoreException e) { - System.out.println("Exception while calling #toDeepDebugString()"); //$NON-NLS-1$ - e.printStackTrace(); - } - return buffer.toString(); - } - - public String toString() { - return absolutePath(); - } -} +/******************************************************************************* + * Copyright (c) 2004, 2011 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 + * Julian Chen - fix for bug #92572, jclRM + *******************************************************************************/ +package org.eclipse.core.internal.preferences; + +import java.io.*; +import java.util.*; +import org.eclipse.core.internal.runtime.RuntimeLog; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.preferences.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; + +/** + * Represents a node in the Eclipse preference node hierarchy. This class + * is used as a default implementation/super class for those nodes which + * belong to scopes which are contributed by the Platform. + * + * Implementation notes: + * + * - For thread safety, we always synchronize on the node object when writing + * the children or properties fields. Must ensure we don't synchronize when calling + * client code such as listeners. + * + * @since 3.0 + */ +public class EclipsePreferences implements IEclipsePreferences, IScope { + + public static final String DEFAULT_PREFERENCES_DIRNAME = ".settings"; //$NON-NLS-1$ + public static final String PREFS_FILE_EXTENSION = "prefs"; //$NON-NLS-1$ + protected static final IEclipsePreferences[] EMPTY_NODE_ARRAY = new IEclipsePreferences[0]; + protected static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String FALSE = "false"; //$NON-NLS-1$ + private static final String TRUE = "true"; //$NON-NLS-1$ + protected static final String VERSION_KEY = "eclipse.preferences.version"; //$NON-NLS-1$ + protected static final String VERSION_VALUE = "1"; //$NON-NLS-1$ + protected static final String PATH_SEPARATOR = String.valueOf(IPath.SEPARATOR); + protected static final String DOUBLE_SLASH = "//"; //$NON-NLS-1$ + protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + private String cachedPath; + protected Map children; + protected boolean dirty = false; + protected boolean loading = false; + protected final String name; + // the parent of an EclipsePreference node is always an EclipsePreference node. (or null) + protected final EclipsePreferences parent; + protected ImmutableMap properties = ImmutableMap.EMPTY; + protected boolean removed = false; + private ListenerList nodeChangeListeners; + private ListenerList preferenceChangeListeners; + + public static boolean DEBUG_PREFERENCE_GENERAL = false; + public static boolean DEBUG_PREFERENCE_SET = false; + public static boolean DEBUG_PREFERENCE_GET = false; + + protected final static String debugPluginName = "org.eclipse.equinox.preferences"; //$NON-NLS-1$ + + static { + DEBUG_PREFERENCE_GENERAL = PreferencesOSGiUtils.getDefault().getBooleanDebugOption(debugPluginName + "/general", false); //$NON-NLS-1$ + DEBUG_PREFERENCE_SET = PreferencesOSGiUtils.getDefault().getBooleanDebugOption(debugPluginName + "/set", false); //$NON-NLS-1$ + DEBUG_PREFERENCE_GET = PreferencesOSGiUtils.getDefault().getBooleanDebugOption(debugPluginName + "/get", false); //$NON-NLS-1$ + } + + protected class SortedProperties extends Properties { + + private static final long serialVersionUID = 1L; + + public SortedProperties() { + super(); + } + + /* (non-Javadoc) + * @see java.util.Hashtable#keys() + */ + public synchronized Enumeration keys() { + TreeSet set = new TreeSet(); + for (Enumeration e = super.keys(); e.hasMoreElements();) + set.add(e.nextElement()); + return Collections.enumeration(set); + } + + /* (non-Javadoc) + * @see java.util.Hashtable#entrySet() + */ + public Set entrySet() { + TreeSet set = new TreeSet(new Comparator() { + public int compare(Object e1, Object e2) { + String s1 = (String) ((Map.Entry) e1).getKey(); + String s2 = (String) ((Map.Entry) e2).getKey(); + return s1.compareTo(s2); + } + }); + for (Iterator i = super.entrySet().iterator(); i.hasNext();) + set.add(i.next()); + return set; + } + } + + public EclipsePreferences() { + this(null, null); + } + + protected EclipsePreferences(EclipsePreferences parent, String name) { + super(); + this.parent = parent; + this.name = name; + this.cachedPath = null; // make sure the cached path is cleared after setting the parent + } + + /* + * @see org.osgi.service.prefs.Preferences#absolutePath() + */ + public String absolutePath() { + if (cachedPath == null) { + if (parent == null) + cachedPath = PATH_SEPARATOR; + else { + String parentPath = parent.absolutePath(); + // if the parent is the root then we don't have to add a separator + // between the parent path and our path + if (parentPath.length() == 1) + cachedPath = parentPath + name(); + else + cachedPath = parentPath + PATH_SEPARATOR + name(); + } + } + return cachedPath; + } + + public void accept(IPreferenceNodeVisitor visitor) throws BackingStoreException { + if (!visitor.visit(this)) + return; + IEclipsePreferences[] toVisit = getChildren(true); + for (int i = 0; i < toVisit.length; i++) + toVisit[i].accept(visitor); + } + + protected synchronized IEclipsePreferences addChild(String childName, IEclipsePreferences child) { + //Thread safety: synchronize method to protect modification of children field + if (children == null) + children = Collections.synchronizedMap(new HashMap()); + children.put(childName, child == null ? (Object) childName : child); + return child; + } + + /* + * @see org.eclipse.core.runtime.IEclipsePreferences#addNodeChangeListener(org.eclipse.core.runtime.IEclipsePreferences.INodeChangeListener) + */ + public void addNodeChangeListener(INodeChangeListener listener) { + checkRemoved(); + if (nodeChangeListeners == null) + nodeChangeListeners = new ListenerList(); + nodeChangeListeners.add(listener); + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Added preference node change listener: " + listener + " to: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* + * @see org.eclipse.core.runtime.IEclipsePreferences#addPreferenceChangeListener(org.eclipse.core.runtime.IEclipsePreferences.IPreferenceChangeListener) + */ + public void addPreferenceChangeListener(IPreferenceChangeListener listener) { + checkRemoved(); + if (preferenceChangeListeners == null) + preferenceChangeListeners = new ListenerList(); + preferenceChangeListeners.add(listener); + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Added preference property change listener: " + listener + " to: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + private IEclipsePreferences calculateRoot() { + IEclipsePreferences result = this; + while (result.parent() != null) + result = (IEclipsePreferences) result.parent(); + return result; + } + + /* + * Convenience method for throwing an exception when methods + * are called on a removed node. + */ + protected void checkRemoved() { + if (removed) + throw new IllegalStateException(NLS.bind(PrefsMessages.preferences_removedNode, name)); + } + + /* + * @see org.osgi.service.prefs.Preferences#childrenNames() + */ + public String[] childrenNames() { + // illegal state if this node has been removed + checkRemoved(); + return internalChildNames(); + } + + protected String[] internalChildNames() { + Map temp = children; + if (temp == null || temp.size() == 0) + return EMPTY_STRING_ARRAY; + return (String[]) temp.keySet().toArray(EMPTY_STRING_ARRAY); + } + + /* + * @see org.osgi.service.prefs.Preferences#clear() + */ + public void clear() { + // illegal state if this node has been removed + checkRemoved(); + // call each one separately (instead of Properties.clear) so + // clients get change notification + String[] keys = properties.keys(); + for (int i = 0; i < keys.length; i++) + remove(keys[i]); + makeDirty(); + } + + protected String[] computeChildren(IPath root) { + if (root == null) + return EMPTY_STRING_ARRAY; + IPath dir = root.append(DEFAULT_PREFERENCES_DIRNAME); + final ArrayList result = new ArrayList(); + final String extension = '.' + PREFS_FILE_EXTENSION; + File file = dir.toFile(); + File[] totalFiles = file.listFiles(); + if (totalFiles != null) { + for (int i = 0; i < totalFiles.length; i++) { + if (totalFiles[i].isFile()) { + String filename = totalFiles[i].getName(); + if (filename.endsWith(extension)) { + String shortName = filename.substring(0, filename.length() - extension.length()); + result.add(shortName); + } + } + } + } + return (String[]) result.toArray(EMPTY_STRING_ARRAY); + } + + protected IPath computeLocation(IPath root, String qualifier) { + return root == null ? null : root.append(DEFAULT_PREFERENCES_DIRNAME).append(qualifier).addFileExtension(PREFS_FILE_EXTENSION); + } + + /* + * Version 1 (current version) + * path/key=value + */ + protected static void convertFromProperties(EclipsePreferences node, Properties table, boolean notify) { + String version = table.getProperty(VERSION_KEY); + if (version == null || !VERSION_VALUE.equals(version)) { + // ignore for now + } + table.remove(VERSION_KEY); + for (Iterator i = table.keySet().iterator(); i.hasNext();) { + String fullKey = (String) i.next(); + String value = table.getProperty(fullKey); + if (value != null) { + String[] splitPath = decodePath(fullKey); + String path = splitPath[0]; + path = makeRelative(path); + String key = splitPath[1]; + if (DEBUG_PREFERENCE_SET) + PrefsMessages.message("Setting preference: " + path + '/' + key + '=' + value); //$NON-NLS-1$ + //use internal methods to avoid notifying listeners + EclipsePreferences childNode = (EclipsePreferences) node.internalNode(path, false, null); + String oldValue = childNode.internalPut(key, value); + // notify listeners if applicable + if (notify && !value.equals(oldValue)) + childNode.firePreferenceEvent(key, oldValue, value); + } + } + PreferencesService.getDefault().shareStrings(); + } + + /* + * Helper method to persist a Properties object to the filesystem. We use this + * helper so we can remove the date/timestamp that Properties#store always + * puts in the file. + */ + protected static void write(Properties properties, IPath location) throws BackingStoreException { + // create the parent dirs if they don't exist + File parentFile = location.toFile().getParentFile(); + if (parentFile == null) + return; + parentFile.mkdirs(); + + OutputStream output = null; + try { + output = new BufferedOutputStream(new FileOutputStream(new File(location.toOSString()))); + output.write(removeTimestampFromTable(properties).getBytes("UTF-8")); //$NON-NLS-1$ + output.flush(); + } catch (IOException e) { + String message = NLS.bind(PrefsMessages.preferences_saveException, location); + log(new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e)); + throw new BackingStoreException(message); + } finally { + if (output != null) + try { + output.close(); + } catch (IOException e) { + // ignore + } + } + } + + protected static String removeTimestampFromTable(Properties properties) throws IOException { + // store the properties in a string and then skip the first line (date/timestamp) + ByteArrayOutputStream output = new ByteArrayOutputStream(); + try { + properties.store(output, null); + } finally { + output.close(); + } + String string = output.toString("UTF-8"); //$NON-NLS-1$ + String separator = System.getProperty("line.separator"); //$NON-NLS-1$ + return string.substring(string.indexOf(separator) + separator.length()); + } + + /* + * Helper method to convert this node to a Properties file suitable + * for persistence. + */ + protected Properties convertToProperties(Properties result, String prefix) throws BackingStoreException { + // add the key/value pairs from this node + boolean addSeparator = prefix.length() != 0; + //thread safety: copy reference in case of concurrent change + ImmutableMap temp = properties; + String[] keys = temp.keys(); + for (int i = 0, imax = keys.length; i < imax; i++) { + String value = temp.get(keys[i]); + if (value != null) + result.put(encodePath(prefix, keys[i]), value); + } + // recursively add the child information + IEclipsePreferences[] childNodes = getChildren(true); + for (int i = 0; i < childNodes.length; i++) { + EclipsePreferences child = (EclipsePreferences) childNodes[i]; + String fullPath = addSeparator ? prefix + PATH_SEPARATOR + child.name() : child.name(); + child.convertToProperties(result, fullPath); + } + PreferencesService.getDefault().shareStrings(); + return result; + } + + /* + * @see org.eclipse.core.runtime.preferences.IScope#create(org.eclipse.core.runtime.preferences.IEclipsePreferences) + */ + public IEclipsePreferences create(IEclipsePreferences nodeParent, String nodeName) { + return create((EclipsePreferences) nodeParent, nodeName, null); + } + + protected boolean isLoading() { + return loading; + } + + protected void setLoading(boolean isLoading) { + loading = isLoading; + } + + public IEclipsePreferences create(EclipsePreferences nodeParent, String nodeName, Object context) { + EclipsePreferences result = internalCreate(nodeParent, nodeName, context); + nodeParent.addChild(nodeName, result); + IEclipsePreferences loadLevel = result.getLoadLevel(); + + // if this node or a parent node is not the load level then return + if (loadLevel == null) + return result; + + // if the result node is not a load level, then a child must be + if (result != loadLevel) + return result; + + // the result node is a load level + if (isAlreadyLoaded(result) || result.isLoading()) + return result; + try { + result.setLoading(true); + result.loadLegacy(); + result.load(); + result.loaded(); + result.flush(); + } catch (BackingStoreException e) { + IPath location = result.getLocation(); + String message = NLS.bind(PrefsMessages.preferences_loadException, location == null ? EMPTY_STRING : location.toString()); + IStatus status = new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e); + RuntimeLog.log(status); + } finally { + result.setLoading(false); + } + return result; + } + + /* + * @see org.osgi.service.prefs.Preferences#flush() + */ + synchronized public void flush() throws BackingStoreException { + // illegal state if this node has been removed + checkRemoved(); + + IEclipsePreferences loadLevel = getLoadLevel(); + + // if this node or a parent is not the load level, then flush the children + if (loadLevel == null) { + String[] childrenNames = childrenNames(); + for (int i = 0; i < childrenNames.length; i++) + node(childrenNames[i]).flush(); + return; + } + + // a parent is the load level for this node + if (this != loadLevel) { + loadLevel.flush(); + return; + } + + // this node is a load level + // any work to do? + if (!dirty) + return; + //remove dirty bit before saving, to ensure that concurrent + //changes during save mark the store as dirty + dirty = false; + try { + save(); + } catch (BackingStoreException e) { + //mark it dirty again because the save failed + dirty = true; + throw e; + } + } + + /* + * @see org.osgi.service.prefs.Preferences#get(java.lang.String, java.lang.String) + */ + public String get(String key, String defaultValue) { + String value = internalGet(key); + return value == null ? defaultValue : value; + } + + /* + * @see org.osgi.service.prefs.Preferences#getBoolean(java.lang.String, boolean) + */ + public boolean getBoolean(String key, boolean defaultValue) { + String value = internalGet(key); + return value == null ? defaultValue : TRUE.equalsIgnoreCase(value); + } + + /* + * @see org.osgi.service.prefs.Preferences#getByteArray(java.lang.String, byte[]) + */ + public byte[] getByteArray(String key, byte[] defaultValue) { + String value = internalGet(key); + return value == null ? defaultValue : Base64.decode(value.getBytes()); + } + + /* + * Return a boolean value indicating whether or not a child with the given + * name is known to this node. + */ + protected synchronized boolean childExists(String childName) { + if (children == null) + return false; + return children.get(childName) != null; + } + + /** + * Thread safe way to obtain a child for a given key. Returns the child + * that matches the given key, or null if there is no matching child. + */ + protected IEclipsePreferences getChild(String key, Object context, boolean create) { + synchronized (this) { + if (children == null) + return null; + Object value = children.get(key); + if (value == null) + return null; + if (value instanceof IEclipsePreferences) + return (IEclipsePreferences) value; + // if we aren't supposed to create this node, then + // just return null + if (!create) + return null; + } + return addChild(key, create(this, key, context)); + } + + /** + * Thread safe way to obtain all children of this node. Never returns null. + */ + protected IEclipsePreferences[] getChildren(boolean create) { + ArrayList result = new ArrayList(); + String[] names = internalChildNames(); + for (int i = 0; i < names.length; i++) { + IEclipsePreferences child = getChild(names[i], null, create); + if (child != null) + result.add(child); + } + return (IEclipsePreferences[]) result.toArray(EMPTY_NODE_ARRAY); + } + + /* + * @see org.osgi.service.prefs.Preferences#getDouble(java.lang.String, double) + */ + public double getDouble(String key, double defaultValue) { + String value = internalGet(key); + double result = defaultValue; + if (value != null) + try { + result = Double.parseDouble(value); + } catch (NumberFormatException e) { + // use default + } + return result; + } + + /* + * @see org.osgi.service.prefs.Preferences#getFloat(java.lang.String, float) + */ + public float getFloat(String key, float defaultValue) { + String value = internalGet(key); + float result = defaultValue; + if (value != null) + try { + result = Float.parseFloat(value); + } catch (NumberFormatException e) { + // use default + } + return result; + } + + /* + * @see org.osgi.service.prefs.Preferences#getInt(java.lang.String, int) + */ + public int getInt(String key, int defaultValue) { + String value = internalGet(key); + int result = defaultValue; + if (value != null) + try { + result = Integer.parseInt(value); + } catch (NumberFormatException e) { + // use default + } + return result; + } + + protected IEclipsePreferences getLoadLevel() { + return null; + } + + /* + * Subclasses to over-ride + */ + protected IPath getLocation() { + return null; + } + + /* + * @see org.osgi.service.prefs.Preferences#getLong(java.lang.String, long) + */ + public long getLong(String key, long defaultValue) { + String value = internalGet(key); + long result = defaultValue; + if (value != null) + try { + result = Long.parseLong(value); + } catch (NumberFormatException e) { + // use default + } + return result; + } + + protected EclipsePreferences internalCreate(EclipsePreferences nodeParent, String nodeName, Object context) { + return new EclipsePreferences(nodeParent, nodeName); + } + + /** + * Returns the existing value at the given key, or null if + * no such value exists. + */ + protected String internalGet(String key) { + // throw NPE if key is null + if (key == null) + throw new NullPointerException(); + // illegal state if this node has been removed + checkRemoved(); + String result = properties.get(key); + if (DEBUG_PREFERENCE_GET) + PrefsMessages.message("Getting preference value: " + absolutePath() + '/' + key + "->" + result); //$NON-NLS-1$ //$NON-NLS-2$ + return result; + } + + /** + * Implements the node(String) method, and optionally notifies listeners. + */ + protected IEclipsePreferences internalNode(String path, boolean notify, Object context) { + + // illegal state if this node has been removed + checkRemoved(); + + // short circuit this node + if (path.length() == 0) + return this; + + // if we have an absolute path use the root relative to + // this node instead of the global root + // in case we have a different hierarchy. (e.g. export) + if (path.charAt(0) == IPath.SEPARATOR) + return (IEclipsePreferences) calculateRoot().node(path.substring(1)); + + int index = path.indexOf(IPath.SEPARATOR); + String key = index == -1 ? path : path.substring(0, index); + boolean added = false; + IEclipsePreferences child = getChild(key, context, true); + if (child == null) { + child = create(this, key, context); + added = true; + } + // notify listeners if a child was added + if (added && notify) + fireNodeEvent(new NodeChangeEvent(this, child), true); + return (IEclipsePreferences) child.node(index == -1 ? EMPTY_STRING : path.substring(index + 1)); + } + + /** + * Stores the given (key,value) pair, performing lazy initialization of the + * properties field if necessary. Returns the old value for the given key, + * or null if no value existed. + */ + protected String internalPut(String key, String newValue) { + // illegal state if this node has been removed + checkRemoved(); + String oldValue = properties.get(key); + if (oldValue != null && oldValue.equals(newValue)) + return oldValue; + if (DEBUG_PREFERENCE_SET) + PrefsMessages.message("Setting preference: " + absolutePath() + '/' + key + '=' + newValue); //$NON-NLS-1$ + properties = properties.put(key, newValue); + return oldValue; + } + + /* + * Subclasses to over-ride. + */ + protected boolean isAlreadyLoaded(IEclipsePreferences node) { + return true; + } + + /* + * @see org.osgi.service.prefs.Preferences#keys() + */ + public String[] keys() { + // illegal state if this node has been removed + checkRemoved(); + return properties.keys(); + } + + /** + * Loads the preference node. This method returns silently if the node does not exist + * in the backing store (for example non-existent project). + * + * @throws BackingStoreException if the node exists in the backing store but it + * could not be loaded + */ + protected void load() throws BackingStoreException { + load(getLocation()); + } + + protected static Properties loadProperties(IPath location) throws BackingStoreException { + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Loading preferences from file: " + location); //$NON-NLS-1$ + InputStream input = null; + Properties result = new Properties(); + try { + input = new BufferedInputStream(new FileInputStream(location.toFile())); + result.load(input); + } catch (FileNotFoundException e) { + // file doesn't exist but that's ok. + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Preference file does not exist: " + location); //$NON-NLS-1$ + return result; + } catch (IOException e) { + String message = NLS.bind(PrefsMessages.preferences_loadException, location); + log(new Status(IStatus.INFO, PrefsMessages.OWNER_NAME, IStatus.INFO, message, e)); + throw new BackingStoreException(message); + } finally { + if (input != null) + try { + input.close(); + } catch (IOException e) { + // ignore + } + } + return result; + } + + protected void load(IPath location) throws BackingStoreException { + if (location == null) { + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Unable to determine location of preference file for node: " + absolutePath()); //$NON-NLS-1$ + return; + } + Properties fromDisk = loadProperties(location); + convertFromProperties(this, fromDisk, false); + } + + protected void loaded() { + // do nothing + } + + protected void loadLegacy() { + // sub-classes to over-ride if necessary + } + + public static void log(IStatus status) { + RuntimeLog.log(status); + } + + protected void makeDirty() { + EclipsePreferences node = this; + while (node != null && !node.removed) { + node.dirty = true; + node = (EclipsePreferences) node.parent(); + } + } + + public boolean isDirty() { + return dirty; + } + + /* + * @see org.osgi.service.prefs.Preferences#name() + */ + public String name() { + return name; + } + + /* + * @see org.osgi.service.prefs.Preferences#node(java.lang.String) + */ + public Preferences node(String pathName) { + return internalNode(pathName, true, null); + } + + protected void fireNodeEvent(final NodeChangeEvent event, final boolean added) { + if (nodeChangeListeners == null) + return; + Object[] listeners = nodeChangeListeners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + final INodeChangeListener listener = (INodeChangeListener) listeners[i]; + ISafeRunnable job = new ISafeRunnable() { + public void handleException(Throwable exception) { + // already logged in Platform#run() + } + + public void run() throws Exception { + if (added) + listener.added(event); + else + listener.removed(event); + } + }; + SafeRunner.run(job); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#nodeExists(java.lang.String) + */ + public boolean nodeExists(String path) throws BackingStoreException { + // short circuit for checking this node + if (path.length() == 0) + return !removed; + + // illegal state if this node has been removed. + // do this AFTER checking for the empty string. + checkRemoved(); + + // use the root relative to this node instead of the global root + // in case we have a different hierarchy. (e.g. export) + if (path.charAt(0) == IPath.SEPARATOR) + return calculateRoot().nodeExists(path.substring(1)); + + int index = path.indexOf(IPath.SEPARATOR); + boolean noSlash = index == -1; + + // if we are looking for a simple child then just look in the table and return + if (noSlash) + return childExists(path); + + // otherwise load the parent of the child and then recursively ask + String childName = path.substring(0, index); + if (!childExists(childName)) + return false; + IEclipsePreferences child = getChild(childName, null, true); + if (child == null) + return false; + return child.nodeExists(path.substring(index + 1)); + } + + /* + * @see org.osgi.service.prefs.Preferences#parent() + */ + public Preferences parent() { + // illegal state if this node has been removed + checkRemoved(); + return parent; + } + + /* + * Convenience method for notifying preference change listeners. + */ + protected void firePreferenceEvent(String key, Object oldValue, Object newValue) { + if (preferenceChangeListeners == null) + return; + Object[] listeners = preferenceChangeListeners.getListeners(); + final PreferenceChangeEvent event = new PreferenceChangeEvent(this, key, oldValue, newValue); + for (int i = 0; i < listeners.length; i++) { + final IPreferenceChangeListener listener = (IPreferenceChangeListener) listeners[i]; + ISafeRunnable job = new ISafeRunnable() { + public void handleException(Throwable exception) { + // already logged in Platform#run() + } + + public void run() throws Exception { + listener.preferenceChange(event); + } + }; + SafeRunner.run(job); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#put(java.lang.String, java.lang.String) + */ + public void put(String key, String newValue) { + if (key == null || newValue == null) + throw new NullPointerException(); + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#putBoolean(java.lang.String, boolean) + */ + public void putBoolean(String key, boolean value) { + if (key == null) + throw new NullPointerException(); + String newValue = value ? TRUE : FALSE; + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#putByteArray(java.lang.String, byte[]) + */ + public void putByteArray(String key, byte[] value) { + if (key == null || value == null) + throw new NullPointerException(); + String newValue = new String(Base64.encode(value)); + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#putDouble(java.lang.String, double) + */ + public void putDouble(String key, double value) { + if (key == null) + throw new NullPointerException(); + String newValue = Double.toString(value); + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#putFloat(java.lang.String, float) + */ + public void putFloat(String key, float value) { + if (key == null) + throw new NullPointerException(); + String newValue = Float.toString(value); + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#putInt(java.lang.String, int) + */ + public void putInt(String key, int value) { + if (key == null) + throw new NullPointerException(); + String newValue = Integer.toString(value); + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#putLong(java.lang.String, long) + */ + public void putLong(String key, long value) { + if (key == null) + throw new NullPointerException(); + String newValue = Long.toString(value); + String oldValue = internalPut(key, newValue); + if (!newValue.equals(oldValue)) { + makeDirty(); + firePreferenceEvent(key, oldValue, newValue); + } + } + + /* + * @see org.osgi.service.prefs.Preferences#remove(java.lang.String) + */ + public void remove(String key) { + // illegal state if this node has been removed + checkRemoved(); + String oldValue = properties.get(key); + if (oldValue == null) + return; + properties = properties.removeKey(key); + makeDirty(); + firePreferenceEvent(key, oldValue, null); + } + + /* + * @see org.osgi.service.prefs.Preferences#removeNode() + */ + public void removeNode() throws BackingStoreException { + // illegal state if this node has been removed + checkRemoved(); + // clear all the property values. do it "the long way" so + // everyone gets notification + String[] keys = keys(); + for (int i = 0; i < keys.length; i++) + remove(keys[i]); + // don't remove the global root or the scope root from the + // parent but remove all its children + if (parent != null && !(parent instanceof RootPreferences)) { + // remove the node from the parent's collection and notify listeners + removed = true; + parent.removeNode(this); + } + IEclipsePreferences[] childNodes = getChildren(false); + for (int i = 0; i < childNodes.length; i++) + try { + childNodes[i].removeNode(); + } catch (IllegalStateException e) { + // ignore since we only get this exception if we have already + // been removed. no work to do. + } + } + + /* + * Remove the child from the collection and notify the listeners if something + * was actually removed. + */ + protected void removeNode(IEclipsePreferences child) { + boolean wasRemoved = false; + synchronized (this) { + if (children != null) { + wasRemoved = children.remove(child.name()) != null; + if (wasRemoved) + makeDirty(); + if (children.isEmpty()) + children = null; + } + } + if (wasRemoved) + fireNodeEvent(new NodeChangeEvent(this, child), false); + } + + /* + * Remove non-initialized node from the collection. + */ + protected void removeNode(String key) { + synchronized (this) { + if (children != null) { + boolean wasRemoved = children.remove(key) != null; + if (wasRemoved) + makeDirty(); + if (children.isEmpty()) + children = null; + } + } + } + + /* + * @see org.eclipse.core.runtime.IEclipsePreferences#removeNodeChangeListener(org.eclipse.core.runtime.IEclipsePreferences.removeNodeChangeListener) + */ + public void removeNodeChangeListener(INodeChangeListener listener) { + checkRemoved(); + if (nodeChangeListeners == null) + return; + nodeChangeListeners.remove(listener); + if (nodeChangeListeners.size() == 0) + nodeChangeListeners = null; + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Removed preference node change listener: " + listener + " from: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /* + * @see org.eclipse.core.runtime.IEclipsePreferences#removePreferenceChangeListener(org.eclipse.core.runtime.IEclipsePreferences.IPreferenceChangeListener) + */ + public void removePreferenceChangeListener(IPreferenceChangeListener listener) { + checkRemoved(); + if (preferenceChangeListeners == null) + return; + preferenceChangeListeners.remove(listener); + if (preferenceChangeListeners.size() == 0) + preferenceChangeListeners = null; + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Removed preference property change listener: " + listener + " from: " + absolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Saves the preference node. This method returns silently if the node does not exist + * in the backing store (for example non-existent project) + * + * @throws BackingStoreException if the node exists in the backing store but it + * could not be saved + */ + protected void save() throws BackingStoreException { + save(getLocation()); + } + + protected void save(IPath location) throws BackingStoreException { + if (location == null) { + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Unable to determine location of preference file for node: " + absolutePath()); //$NON-NLS-1$ + return; + } + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Saving preferences to file: " + location); //$NON-NLS-1$ + Properties table = convertToProperties(new SortedProperties(), EMPTY_STRING); + if (table.isEmpty()) { + // nothing to save. delete existing file if one exists. + if (location.toFile().exists() && !location.toFile().delete()) { + String message = NLS.bind(PrefsMessages.preferences_failedDelete, location); + log(new Status(IStatus.WARNING, PrefsMessages.OWNER_NAME, IStatus.WARNING, message, null)); + } + return; + } + table.put(VERSION_KEY, VERSION_VALUE); + write(table, location); + } + + /** + * Traverses the preference hierarchy rooted at this node, and adds + * all preference key and value strings to the provided pool. If an added + * string was already in the pool, all references will be replaced with the + * canonical copy of the string. + * + * @param pool The pool to share strings in + */ + public void shareStrings(StringPool pool) { + properties.shareStrings(pool); + IEclipsePreferences[] myChildren = getChildren(false); + for (int i = 0; i < myChildren.length; i++) + if (myChildren[i] instanceof EclipsePreferences) + ((EclipsePreferences) myChildren[i]).shareStrings(pool); + } + + /* + * Encode the given path and key combo to a form which is suitable for + * persisting or using when searching. If the key contains a slash character + * then we must use a double-slash to indicate the end of the + * path/the beginning of the key. + */ + public static String encodePath(String path, String key) { + String result; + int pathLength = path == null ? 0 : path.length(); + if (key.indexOf(IPath.SEPARATOR) == -1) { + if (pathLength == 0) + result = key; + else + result = path + IPath.SEPARATOR + key; + } else { + if (pathLength == 0) + result = DOUBLE_SLASH + key; + else + result = path + DOUBLE_SLASH + key; + } + return result; + } + + /* + * Return the segment from the given path or null. + * "segment" parameter is 0-based. + */ + public static String getSegment(String path, int segment) { + int start = path.indexOf(IPath.SEPARATOR) == 0 ? 1 : 0; + int end = path.indexOf(IPath.SEPARATOR, start); + if (end == path.length() - 1) + end = -1; + for (int i = 0; i < segment; i++) { + if (end == -1) + return null; + start = end + 1; + end = path.indexOf(IPath.SEPARATOR, start); + } + if (end == -1) + end = path.length(); + return path.substring(start, end); + } + + public static int getSegmentCount(String path) { + StringTokenizer tokenizer = new StringTokenizer(path, String.valueOf(IPath.SEPARATOR)); + return tokenizer.countTokens(); + } + + /* + * Return a relative path + */ + public static String makeRelative(String path) { + String result = path; + if (path == null) + return EMPTY_STRING; + if (path.length() > 0 && path.charAt(0) == IPath.SEPARATOR) + result = path.length() == 0 ? EMPTY_STRING : path.substring(1); + return result; + } + + /* + * Return a 2 element String array. + * element 0 - the path + * element 1 - the key + * The path may be null. + * The key is never null. + */ + public static String[] decodePath(String fullPath) { + String key = null; + String path = null; + + // check to see if we have an indicator which tells us where the path ends + int index = fullPath.indexOf(DOUBLE_SLASH); + if (index == -1) { + // we don't have a double-slash telling us where the path ends + // so the path is up to the last slash character + int lastIndex = fullPath.lastIndexOf(IPath.SEPARATOR); + if (lastIndex == -1) { + key = fullPath; + } else { + path = fullPath.substring(0, lastIndex); + key = fullPath.substring(lastIndex + 1); + } + } else { + // the child path is up to the double-slash and the key + // is the string after it + path = fullPath.substring(0, index); + key = fullPath.substring(index + 2); + } + + // adjust if we have an absolute path + if (path != null) + if (path.length() == 0) + path = null; + else if (path.charAt(0) == IPath.SEPARATOR) + path = path.substring(1); + + return new String[] {path, key}; + } + + /* + * @see org.osgi.service.prefs.Preferences#sync() + */ + + public void sync() throws BackingStoreException { + // illegal state if this node has been removed + checkRemoved(); + IEclipsePreferences node = getLoadLevel(); + if (node == null) { + if (DEBUG_PREFERENCE_GENERAL) + PrefsMessages.message("Preference node is not a load root: " + absolutePath()); //$NON-NLS-1$ + return; + } + if (node instanceof EclipsePreferences) { + ((EclipsePreferences) node).load(); + node.flush(); + } + } + + public String toDeepDebugString() { + final StringBuffer buffer = new StringBuffer(); + IPreferenceNodeVisitor visitor = new IPreferenceNodeVisitor() { + public boolean visit(IEclipsePreferences node) throws BackingStoreException { + buffer.append(node); + buffer.append('\n'); + String[] keys = node.keys(); + for (int i = 0; i < keys.length; i++) { + buffer.append(node.absolutePath()); + buffer.append(PATH_SEPARATOR); + buffer.append(keys[i]); + buffer.append('='); + buffer.append(node.get(keys[i], "*default*")); //$NON-NLS-1$ + buffer.append('\n'); + } + return true; + } + }; + try { + accept(visitor); + } catch (BackingStoreException e) { + System.out.println("Exception while calling #toDeepDebugString()"); //$NON-NLS-1$ + e.printStackTrace(); + } + return buffer.toString(); + } + + public String toString() { + return absolutePath(); + } +} diff --git a/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/BackingStoreException.java b/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/BackingStoreException.java index 9f4bca221..86f6e3cc9 100644 --- a/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/BackingStoreException.java +++ b/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/BackingStoreException.java @@ -19,7 +19,7 @@ package org.osgi.service.prefs; * Thrown to indicate that a preferences operation could not complete because of * a failure in the backing store, or a failure to contact the backing store. * - * @version $Id: 86f6e3cc926b2ea3875e000e90b0700a75f2a7c7 $ + * @version $Id$ */ public class BackingStoreException extends Exception { static final long serialVersionUID = -1415637364122829574L; diff --git a/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/Preferences.java b/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/Preferences.java index 513d6cd79..481de91d7 100644 --- a/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/Preferences.java +++ b/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/Preferences.java @@ -108,7 +108,7 @@ package org.osgi.service.prefs; * preference data. * * @noimplement - * @version $Id: 481de91d7ba8a3274ad7ded1ea26f254564baea0 $ + * @version $Id$ */ public interface Preferences { /** diff --git a/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/PreferencesService.java b/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/PreferencesService.java index 6371dbf95..bcb430ac7 100644 --- a/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/PreferencesService.java +++ b/bundles/org.eclipse.equinox.preferences/src/org/osgi/service/prefs/PreferencesService.java @@ -29,7 +29,7 @@ package org.osgi.service.prefs; * {@code PreferencesService} object to that bundle. * * @noimplement - * @version $Id: bcb430ac769863b4239575c1edeedc23fc5ab097 $ + * @version $Id$ */ public interface PreferencesService { /** diff --git a/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/Resolver.java b/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/Resolver.java index cc84ddc3d..5735a30be 100644 --- a/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/Resolver.java +++ b/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/Resolver.java @@ -32,7 +32,7 @@ import org.osgi.framework.resource.Wire; * specified {@link Resource resources} based on a supplied {@link Environment}. * * @ThreadSafe - * @version $Id: 93375420122cbe48e6fba5af207af43826a508fa $ + * @version $Id$ */ public interface Resolver { /** diff --git a/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/package-info.java b/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/package-info.java index be979c503..ffe26e5b9 100644 --- a/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/package-info.java +++ b/bundles/org.eclipse.equinox.resolver/src/org/osgi/service/resolver/package-info.java @@ -32,7 +32,7 @@ *

* {@code Import-Package: org.osgi.service.resolver; version="[1.0,1.1)"} * - * @version $Id: ffe26e5b960ebceb84699fd1cb8f211d9a386bf4 $ + * @version $Id$ */ package org.osgi.service.resolver; \ No newline at end of file -- cgit v1.2.3