FELIX-879 Replace Vector by Collection and copy provided
collection values into internal collections

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@734494 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin/src/main/java/org/apache/felix/cm/file/ConfigurationHandler.java b/configadmin/src/main/java/org/apache/felix/cm/file/ConfigurationHandler.java
index 16992cd..e2ca814 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/file/ConfigurationHandler.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/file/ConfigurationHandler.java
@@ -29,14 +29,16 @@
 import java.io.PushbackReader;
 import java.io.Writer;
 import java.lang.reflect.Array;
+import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Collection;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-import java.util.Vector;
 
 
 /**
@@ -46,17 +48,17 @@
  * {@link FilePersistenceManager} class.
  * 
  * <pre>
- cfg = prop "=" value .
- prop = symbolic-name . // 1.4.2 of OSGi Core Specification
- symbolic-name = token { "." token } .
- token = { [ 0..9 ] | [ a..z ] | [ A..Z ] | '_' | '-' } .
- value = [ type ] ( "[" values "]" | "(" values ")" | simple ) .
- values = simple { "," simple } .
- simple = """ stringsimple """ .
- type = // 1-char type code .
- stringsimple = // quoted string representation of the value .
+ * cfg = prop &quot;=&quot; value .
+ *  prop = symbolic-name . // 1.4.2 of OSGi Core Specification
+ *  symbolic-name = token { &quot;.&quot; token } .
+ *  token = { [ 0..9 ] | [ a..z ] | [ A..Z ] | '_' | '-' } .
+ *  value = [ type ] ( &quot;[&quot; values &quot;]&quot; | &quot;(&quot; values &quot;)&quot; | simple ) .
+ *  values = simple { &quot;,&quot; simple } .
+ *  simple = &quot;&quot;&quot; stringsimple &quot;&quot;&quot; .
+ *  type = // 1-char type code .
+ *  stringsimple = // quoted string representation of the value .
  * </pre>
- *
+ * 
  * @author fmeschbe
  */
 public class ConfigurationHandler
@@ -187,11 +189,13 @@
      * This method writes at the current location in the stream and does not
      * close the outputstream.
      * 
-     * @param out The <code>OutputStream</code> to write the configurtion data
-     *      to.
-     * @param properties The <code>Dictionary</code> to write.
-     * 
-     * @throws IOException If an error occurrs writing to the output stream.
+     * @param out
+     *            The <code>OutputStream</code> to write the configurtion data
+     *            to.
+     * @param properties
+     *            The <code>Dictionary</code> to write.
+     * @throws IOException
+     *             If an error occurrs writing to the output stream.
      */
     public static void write( OutputStream out, Dictionary properties ) throws IOException
     {
@@ -201,7 +205,7 @@
         {
             String key = ( String ) ce.nextElement();
 
-            //     cfg = prop "=" value "." .
+            // cfg = prop "=" value "." .
             writeQuoted( bw, key );
             bw.write( TOKEN_EQ );
             writeValue( bw, properties.get( key ) );
@@ -216,18 +220,18 @@
      * Reads configuration data from the given <code>InputStream</code> and
      * returns a new <code>Dictionary</code> object containing the data.
      * <p>
-     * This method reads from the current location in the stream upto the end
-     * of the stream but does not close the stream at the end.
+     * This method reads from the current location in the stream upto the end of
+     * the stream but does not close the stream at the end.
      * 
-     * @param ins The <code>InputStream</code> from which to read the
-     *      configuration data.
-     *      
+     * @param ins
+     *            The <code>InputStream</code> from which to read the
+     *            configuration data.
      * @return A <code>Dictionary</code> object containing the configuration
-     *      data. This object may be empty if the stream contains no
-     *      configuration data.
-     *      
-     * @throws IOException If an error occurrs reading from the stream. This
-     *      exception is also thrown if a syntax error is encountered.
+     *         data. This object may be empty if the stream contains no
+     *         configuration data.
+     * @throws IOException
+     *             If an error occurrs reading from the stream. This exception
+     *             is also thrown if a syntax error is encountered.
      */
     public static Dictionary read( InputStream ins ) throws IOException
     {
@@ -235,12 +239,13 @@
     }
 
 
-    // private constructor, this class is not to be instantiated from the outside
+    // private constructor, this class is not to be instantiated from the
+    // outside
     private ConfigurationHandler()
     {
     }
 
-    //---------- Configuration Input Implementation ---------------------------
+    // ---------- Configuration Input Implementation ---------------------------
 
     private int token;
     private String tokenValue;
@@ -283,11 +288,9 @@
 
 
     /**
-     value = type ( "[" values "]" | "(" values ")" | simple ) .
-     values = value { "," value } .
-     simple = "{" stringsimple "}" .
-     type = // 1-char type code .
-     stringsimple = // quoted string representation of the value .
+     * value = type ( "[" values "]" | "(" values ")" | simple ) . values =
+     * value { "," value } . simple = "{" stringsimple "}" . type = // 1-char
+     * type code . stringsimple = // quoted string representation of the value .
      * 
      * @param pr
      * @return
@@ -316,7 +319,7 @@
                 return readArray( type, pr );
 
             case TOKEN_VEC_OPEN:
-                return readVector( type, pr );
+                return readCollection( type, pr );
 
             case TOKEN_VAL_OPEN:
                 return readSimple( type, pr );
@@ -329,7 +332,7 @@
 
     private Object readArray( int typeCode, PushbackReader pr ) throws IOException
     {
-        Vector vector = new Vector();
+        List list = new ArrayList();
         for ( ;; )
         {
             if ( !checkNext( pr, TOKEN_VAL_OPEN ) )
@@ -344,16 +347,16 @@
                 return null;
             }
 
-            vector.add( value );
+            list.add( value );
 
             int c = read( pr );
             if ( c == TOKEN_ARR_CLOS )
             {
                 Class type = ( Class ) code2Type.get( new Integer( typeCode ) );
-                Object array = Array.newInstance( type, vector.size() );
-                for ( int i = 0; i < vector.size(); i++ )
+                Object array = Array.newInstance( type, list.size() );
+                for ( int i = 0; i < list.size(); i++ )
                 {
-                    Array.set( array, i, vector.get( i ) );
+                    Array.set( array, i, list.get( i ) );
                 }
                 return array;
             }
@@ -369,9 +372,9 @@
     }
 
 
-    private Vector readVector( int typeCode, PushbackReader pr ) throws IOException
+    private Collection readCollection( int typeCode, PushbackReader pr ) throws IOException
     {
-        Vector vector = new Vector();
+        Collection collection = new ArrayList();
         for ( ;; )
         {
             if ( !checkNext( pr, TOKEN_VAL_OPEN ) )
@@ -386,12 +389,12 @@
                 return null;
             }
 
-            vector.add( value );
+            collection.add( value );
 
             int c = read( pr );
             if ( c == TOKEN_VEC_CLOS )
             {
-                return vector;
+                return collection;
             }
             else if ( c < 0 )
             {
@@ -653,7 +656,7 @@
     }
 
 
-    //---------- Configuration Output Implementation --------------------------
+    // ---------- Configuration Output Implementation --------------------------
 
     private static void writeValue( Writer out, Object value ) throws IOException
     {
@@ -662,9 +665,9 @@
         {
             writeArray( out, value );
         }
-        else if ( clazz == Vector.class )
+        else if ( value instanceof Collection )
         {
-            writeVector( out, ( Vector ) value );
+            writeCollection( out, ( Collection ) value );
         }
         else
         {
@@ -694,20 +697,24 @@
     }
 
 
-    private static void writeVector( Writer out, Vector vector ) throws IOException
+    private static void writeCollection( Writer out, Collection collection ) throws IOException
     {
-        if ( vector.isEmpty() )
+        if ( collection.isEmpty() )
         {
             return;
         }
 
-        writeType( out, vector.get( 0 ).getClass() );
+        Iterator ci = collection.iterator();
+        Object firstElement = ci.next();
+
+        writeType( out, firstElement.getClass() );
         out.write( TOKEN_VEC_OPEN );
-        for ( int i = 0; i < vector.size(); i++ )
+        writeSimple( out, firstElement );
+
+        while ( ci.hasNext() )
         {
-            if ( i > 0 )
-                out.write( TOKEN_COMMA );
-            writeSimple( out, vector.get( i ) );
+            out.write( TOKEN_COMMA );
+            writeSimple( out, ci.next() );
         }
         out.write( TOKEN_VEC_CLOS );
     }
diff --git a/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java b/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java
index e254838..374a9d6 100644
--- a/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java
+++ b/configadmin/src/main/java/org/apache/felix/cm/impl/CaseInsensitiveDictionary.java
@@ -19,11 +19,13 @@
 package org.apache.felix.cm.impl;
 
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.Hashtable;
-import java.util.Vector;
+import java.util.Iterator;
 
 
 /**
@@ -77,7 +79,7 @@
 
             // check the value
             Object value = props.get( key );
-            checkValue( value );
+            value = checkValue( value );
 
             // add the key/value pair
             internalMap.put( lowerCase, value );
@@ -156,7 +158,7 @@
         }
 
         checkKey( key );
-        checkValue( value );
+        value = checkValue( value );
 
         String lowerCase = String.valueOf( key ).toLowerCase();
         originalKeys.put( lowerCase, key );
@@ -249,7 +251,7 @@
     }
 
 
-    static void checkValue( Object value )
+    static Object checkValue( Object value )
     {
         Class type;
         if ( value instanceof Object[] )
@@ -261,27 +263,28 @@
             if ( type == Integer.TYPE || type == Long.TYPE || type == Float.TYPE || type == Double.TYPE
                 || type == Byte.TYPE || type == Short.TYPE || type == Character.TYPE || type == Boolean.TYPE )
             {
-                return;
+                return value;
             }
 
         }
-        else if ( value instanceof Vector )
+        else if ( value instanceof Collection )
         {
             // check simple
-            Vector vector = ( Vector ) value;
-            if ( vector.isEmpty() )
+            Collection collection = ( Collection ) value;
+            if ( collection.isEmpty() )
             {
-                throw new IllegalArgumentException( "Vector must not be empty" );
+                throw new IllegalArgumentException( "Collection must not be empty" );
             }
 
-            // ensure all elements have the same type
+            // ensure all elements have the same type and to internal list
+            Collection internalValue = new ArrayList( collection.size() );
             type = null;
-            for ( int i = 0; i < vector.size(); i++ )
+            for ( Iterator ci = collection.iterator(); ci.hasNext(); )
             {
-                Object el = vector.get( i );
+                Object el = ci.next();
                 if ( el == null )
                 {
-                    throw new IllegalArgumentException( "Vector must not contain null elements" );
+                    throw new IllegalArgumentException( "Collection must not contain null elements" );
                 }
                 if ( type == null )
                 {
@@ -289,10 +292,11 @@
                 }
                 else if ( type != el.getClass() )
                 {
-                    throw new IllegalArgumentException( "Vector element types must not be mixed" );
+                    throw new IllegalArgumentException( "Collection element types must not be mixed" );
                 }
+                internalValue.add( el );
             }
-
+            value = internalValue;
         }
         else if ( value != null )
         {
@@ -311,7 +315,7 @@
             || type == Double.class || type == Byte.class || type == Short.class || type == Character.class
             || type == Boolean.class )
         {
-            return;
+            return value;
         }
 
         // not a valid type
diff --git a/configadmin/src/test/java/org/apache/felix/cm/file/FilePersistenceManagerTest.java b/configadmin/src/test/java/org/apache/felix/cm/file/FilePersistenceManagerTest.java
index b125cf3..a76de13 100644
--- a/configadmin/src/test/java/org/apache/felix/cm/file/FilePersistenceManagerTest.java
+++ b/configadmin/src/test/java/org/apache/felix/cm/file/FilePersistenceManagerTest.java
@@ -120,9 +120,18 @@
     public void testVector() throws IOException
     {
         check( "StringVector", new Vector( Arrays.asList( new String[]
-            { "one", "two", "three" } ) ) );
+                                                                     { "one", "two", "three" } ) ) );
         check( "IntegerVector", new Vector( Arrays.asList( new Integer[]
-            { new Integer( 0 ), new Integer( 1 ), new Integer( 2 ) } ) ) );
+                                                                       { new Integer( 0 ), new Integer( 1 ), new Integer( 2 ) } ) ) );
+    }
+    
+    
+    public void testList() throws IOException
+    {
+        check( "StringList", Arrays.asList( new String[]
+            { "one", "two", "three" } ) );
+        check( "IntegerList", Arrays.asList( new Integer[]
+            { new Integer( 0 ), new Integer( 1 ), new Integer( 2 ) } ) );
     }