1 /******************************************************************************* 2 * Copyright (c) 2005, 2018 Cognos Incorporated, IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * Cognos Incorporated - initial API and implementation 13 * IBM Corporation - bug fixes and enhancements 14 *******************************************************************************/ 15 package org.eclipse.equinox.internal.cm; 16 17 import java.io.Serializable; 18 import java.lang.reflect.Array; 19 import java.util.*; 20 import java.util.Map.Entry; 21 22 /** 23 * ConfigurationDictionary holds the actual configuration data and meets the various comparison 24 * requirements of the Configuration Admin Service specification. 25 */ 26 27 public class ConfigurationDictionary extends Dictionary<String, Object> implements Serializable { 28 29 private static final long serialVersionUID = -3583299578203095532L; 30 private static final Collection<Class<?>> simples = Arrays.asList(new Class<?>[] {String.class, Integer.class, Long.class, Float.class, Double.class, Byte.class, Short.class, Character.class, Boolean.class}); 31 private static final Collection<Class<?>> simpleArrays = Arrays.asList(new Class<?>[] {String[].class, Integer[].class, Long[].class, Float[].class, Double[].class, Byte[].class, Short[].class, Character[].class, Boolean[].class}); 32 private static final Collection<Class<?>> primitiveArrays = Arrays.asList(new Class<?>[] {long[].class, int[].class, short[].class, char[].class, byte[].class, double[].class, float[].class, boolean[].class}); 33 34 static class CaseInsensitiveStringComparator implements Comparator<String>, Serializable { 35 private static final long serialVersionUID = 6501536810492374044L; 36 37 @Override compare(String s1, String s2)38 public int compare(String s1, String s2) { 39 return (s1).compareToIgnoreCase(s2); 40 } 41 } 42 43 protected final Map<String, Object> configurationProperties = Collections.synchronizedMap(new TreeMap<>(new CaseInsensitiveStringComparator())); 44 validateValue(Object value)45 private static void validateValue(Object value) { 46 Class<?> clazz = value.getClass(); 47 48 // Is it in the set of simple types 49 if (simples.contains(clazz)) 50 return; 51 52 // Is it an array of primitives or simples 53 if (simpleArrays.contains(clazz) || primitiveArrays.contains(clazz)) 54 return; 55 56 // Is it a Collection of simples 57 if (value instanceof Collection) { 58 for (Object simple : (Collection<?>) value) { 59 Class<?> containedClazz = simple.getClass(); 60 if (!simples.contains(containedClazz)) { 61 throw new IllegalArgumentException(containedClazz.getName() + " in " + clazz.getName()); //$NON-NLS-1$ 62 } 63 } 64 return; 65 } 66 throw new IllegalArgumentException(clazz.getName()); 67 } 68 69 @Override elements()70 public Enumeration<Object> elements() { 71 return new Enumeration<Object>() { 72 final Iterator<Object> valuesIterator = configurationProperties.values().iterator(); 73 74 @Override 75 public boolean hasMoreElements() { 76 return valuesIterator.hasNext(); 77 } 78 79 @Override 80 public Object nextElement() { 81 return valuesIterator.next(); 82 } 83 }; 84 } 85 86 @Override get(Object key)87 public Object get(Object key) { 88 if (key == null) 89 throw new NullPointerException(); 90 return configurationProperties.get(key); 91 } 92 93 @Override isEmpty()94 public boolean isEmpty() { 95 return configurationProperties.isEmpty(); 96 } 97 98 @Override keys()99 public Enumeration<String> keys() { 100 return new Enumeration<String>() { 101 Iterator<String> keysIterator = configurationProperties.keySet().iterator(); 102 103 @Override 104 public boolean hasMoreElements() { 105 return keysIterator.hasNext(); 106 } 107 108 @Override 109 public String nextElement() { 110 return keysIterator.next(); 111 } 112 }; 113 } 114 115 @Override 116 public Object put(String key, Object value) { 117 if (key == null || value == null) 118 throw new NullPointerException(); 119 120 // Will throw an illegal argument exception if not a valid configuration property type 121 validateValue(value); 122 123 return configurationProperties.put(key, value); 124 } 125 126 @Override 127 public Object remove(Object key) { 128 if (key == null) 129 throw new NullPointerException(); 130 return configurationProperties.remove(key); 131 } 132 133 @Override 134 public int size() { 135 return configurationProperties.size(); 136 } 137 138 ConfigurationDictionary copy() { 139 ConfigurationDictionary result = new ConfigurationDictionary(); 140 for (Entry<String, Object> entry : configurationProperties.entrySet()) { 141 String key = entry.getKey(); 142 Object value = entry.getValue(); 143 if (value.getClass().isArray()) { 144 int arrayLength = Array.getLength(value); 145 Object copyOfArray = Array.newInstance(value.getClass().getComponentType(), arrayLength); 146 System.arraycopy(value, 0, copyOfArray, 0, arrayLength); 147 result.configurationProperties.put(key, copyOfArray); 148 } else if (value instanceof Collection) 149 result.configurationProperties.put(key, new ArrayList<>((Collection<?>) value)); 150 else 151 result.configurationProperties.put(key, value); 152 } 153 return result; 154 } 155 } 156