diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java')
-rw-r--r-- | bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java new file mode 100644 index 000000000..a829d2697 --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/serviceregistry/ServiceProperties.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2003, 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.osgi.internal.serviceregistry; + +import java.lang.reflect.Array; +import java.util.*; +import org.eclipse.osgi.framework.util.Headers; +import org.osgi.framework.Constants; + +/** + * Hashtable for service properties. + * + * Supports case-insensitive key lookup. + */ +class ServiceProperties extends Headers<String, Object> { + /** + * Create a properties object for the service. + * + * @param props The properties for this service. + */ + private ServiceProperties(int size, Dictionary<String, ?> props) { + super(size); + + if (props == null) { + return; + } + synchronized (props) { + Enumeration<?> keysEnum = props.keys(); + + while (keysEnum.hasMoreElements()) { + Object key = keysEnum.nextElement(); + + if (key instanceof String) { + String header = (String) key; + + setProperty(header, props.get(header)); + } + } + } + } + + /** + * Create a properties object for the service. + * + * @param props The properties for this service. + */ + ServiceProperties(Dictionary<String, ?> props) { + this((props == null) ? 2 : props.size() + 2, props); + } + + /** + * Get a clone of the value of a service's property. + * + * @param key header name. + * @return Clone of the value of the property or <code>null</code> if there is + * no property by that name. + */ + Object getProperty(String key) { + return cloneValue(get(key)); + } + + /** + * Get the list of key names for the service's properties. + * + * @return The list of property key names. + */ + synchronized String[] getPropertyKeys() { + int size = size(); + + String[] keynames = new String[size]; + + Enumeration<String> keysEnum = keys(); + + for (int i = 0; i < size; i++) { + keynames[i] = keysEnum.nextElement(); + } + + return keynames; + } + + /** + * Put a clone of the property value into this property object. + * + * @param key Name of property. + * @param value Value of property. + * @return previous property value. + */ + synchronized Object setProperty(String key, Object value) { + return set(key, cloneValue(value)); + } + + /** + * Attempt to clone the value if necessary and possible. + * + * For some strange reason, you can test to see of an Object is + * Cloneable but you can't call the clone method since it is + * protected on Object! + * + * @param value object to be cloned. + * @return cloned object or original object if we didn't clone it. + */ + private static Object cloneValue(Object value) { + if (value == null) + return null; + if (value instanceof String) /* shortcut String */ + return value; + if (value instanceof Number) /* shortcut Number */ + return value; + if (value instanceof Character) /* shortcut Character */ + return value; + if (value instanceof Boolean) /* shortcut Boolean */ + return value; + + Class<?> clazz = value.getClass(); + if (clazz.isArray()) { + // Do an array copy + Class<?> type = clazz.getComponentType(); + int len = Array.getLength(value); + Object clonedArray = Array.newInstance(type, len); + System.arraycopy(value, 0, clonedArray, 0, len); + return clonedArray; + } + // must use reflection because Object clone method is protected!! + try { + return clazz.getMethod("clone", (Class<?>[]) null).invoke(value, (Object[]) null); //$NON-NLS-1$ + } catch (Exception e) { + /* clone is not a public method on value's class */ + } catch (Error e) { + /* JCL does not support reflection; try some well known types */ + if (value instanceof Vector<?>) + return ((Vector<?>) value).clone(); + if (value instanceof Hashtable<?, ?>) + return ((Hashtable<?, ?>) value).clone(); + } + return value; + } + + public synchronized String toString() { + String keys[] = getPropertyKeys(); + + int size = keys.length; + + StringBuffer sb = new StringBuffer(20 * size); + + sb.append('{'); + + int n = 0; + for (int i = 0; i < size; i++) { + String key = keys[i]; + if (!key.equals(Constants.OBJECTCLASS)) { + if (n > 0) + sb.append(", "); //$NON-NLS-1$ + + sb.append(key); + sb.append('='); + Object value = get(key); + if (value.getClass().isArray()) { + sb.append('['); + int length = Array.getLength(value); + for (int j = 0; j < length; j++) { + if (j > 0) + sb.append(','); + sb.append(Array.get(value, j)); + } + sb.append(']'); + } else { + sb.append(value); + } + n++; + } + } + + sb.append('}'); + + return sb.toString(); + } +}
\ No newline at end of file |