felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1750501 [2/2] - in /felix/sandbox/cziegeler/configurator: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/configurator/ src/main/java/org/apache/f...
Date Tue, 28 Jun 2016 13:14:21 GMT
Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+public enum ConfigPolicy {
+
+    DEFAULT,
+    FORCE
+}

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigPolicy.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+/**
+ * The state of a configuration.
+ *
+ * The state represents the configurator's view. It might not
+ * reflect the current state of the system. For example if a
+ * configuration is installed through the configurator, it gets
+ * the state "INSTALLED". However if an administrator now deletes
+ * the configuration through any other way like e.g. the web console,
+ * the configuration still has the state "INSTALLED".
+ *
+ */
+public enum ConfigState {
+
+    INSTALL,        // the configuration should be installed
+    UNINSTALL,      // the configuration should be uninstalled
+    INSTALLED,      // the configuration is installed
+    UNINSTALLED,    // the configuration is uninstalled
+    IGNORED         // the configuration is ignored
+}

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigState.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+import java.net.URL;
+import java.util.List;
+
+/**
+ * This object holds all configurations from a single file.
+ * This is only an intermediate object.
+ */
+public class ConfigurationFile implements Comparable<ConfigurationFile> {
+
+    private final URL url;
+
+    private final List<Config> configurations;
+
+    public ConfigurationFile(final URL url, final List<Config> configs) {
+        this.url = url;
+        this.configurations = configs;
+    }
+
+    @Override
+    public int compareTo(final ConfigurationFile o) {
+        return url.getPath().compareTo(o.url.getPath());
+    }
+
+    @Override
+    public String toString() {
+        return "ConfigurationFile [url=" + url + ", configurations=" + configurations + "]";
+    }
+
+    public List<Config> getConfigurations() {
+        return this.configurations;
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/ConfigurationFile.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.configurator.impl.Util;
+import org.apache.felix.configurator.impl.logger.SystemLogger;
+import org.osgi.framework.BundleContext;
+
+public class State extends AbstractState implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /** Serialization version. */
+    private static final int VERSION = 1;
+
+    private static final String FILE_NAME = "state.ser";
+
+    private final Map<Long, Long> bundlesLastModified = new HashMap<Long, Long>();
+
+    private final Set<String> environments = new HashSet<>();
+
+    private volatile Set<String> initialHashes;
+
+    volatile transient boolean envsChanged = true;
+
+    /**
+     * Serialize the object
+     * - write version id
+     * - serialize fields
+     * @param out Object output stream
+     * @throws IOException
+     */
+    private void writeObject(final java.io.ObjectOutputStream out)
+    throws IOException {
+        out.writeInt(VERSION);
+        out.writeObject(bundlesLastModified);
+        out.writeObject(environments);
+        out.writeObject(initialHashes);
+    }
+
+    /**
+     * Deserialize the object
+     * - read version id
+     * - deserialize fields
+     */
+    @SuppressWarnings("unchecked")
+    private void readObject(final java.io.ObjectInputStream in)
+    throws IOException, ClassNotFoundException {
+        final int version = in.readInt();
+        if ( version < 1 || version > VERSION ) {
+            throw new ClassNotFoundException(this.getClass().getName());
+        }
+        Util.setField(this, "bundlesLastModified", in.readObject());
+        Util.setField(this, "environments", in.readObject());
+        initialHashes = (Set<String>) in.readObject();
+    }
+
+    public static State createOrReadState(final BundleContext bc) {
+        final File f = bc.getDataFile(FILE_NAME);
+        if ( f == null || !f.exists() ) {
+            return new State();
+        }
+        try ( final ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f)) ) {
+
+            return (State) ois.readObject();
+        } catch ( final ClassNotFoundException | IOException e ) {
+            SystemLogger.error("Unable to read persisted state from " + f, e);
+            return new State();
+        }
+    }
+
+    public static void writeState(final BundleContext bc, final State state) {
+        final File f = bc.getDataFile(FILE_NAME);
+        if ( f == null ) {
+            // do nothing, no file system support
+            return;
+        }
+        try ( final ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f)) ) {
+            oos.writeObject(state);
+        } catch ( final IOException e) {
+            SystemLogger.error("Unable to persist state to " + f, e);
+        }
+    }
+
+    public Long getLastModified(final long bundleId) {
+        return this.bundlesLastModified.get(bundleId);
+    }
+
+    public void setLastModified(final long bundleId, final long lastModified) {
+        this.bundlesLastModified.put(bundleId, lastModified);
+    }
+
+    public void removeLastModified(final long bundleId) {
+        this.bundlesLastModified.remove(bundleId);
+    }
+
+    public Set<Long> getKnownBundleIds() {
+        return this.bundlesLastModified.keySet();
+    }
+
+    public Set<String> getEnvironments() {
+        return this.environments;
+    }
+
+    public void changeEnvironments(final Set<String> envs) {
+        this.envsChanged = this.environments.equals(envs);
+        this.environments.clear();
+        this.environments.addAll(envs);
+    }
+
+    public boolean environmentsChanged() {
+        return this.envsChanged;
+    }
+
+    public Set<String> getInitialHashes() {
+        return this.initialHashes;
+    }
+
+    public void setInitialHashes(final Set<String> value) {
+        this.initialHashes = value;
+    }
+
+    /**
+     * Add all configurations for a pid
+     * @param pid The pid
+     * @param configs The list of configurations
+     */
+    public void addAll(final String pid, final ConfigList configs) {
+        if ( configs != null ) {
+            ConfigList list = this.getConfigurations().get(pid);
+            if ( list == null ) {
+                list = new ConfigList();
+                this.getConfigurations().put(pid, list);
+            }
+
+            list.addAll(configs);
+        }
+    }
+
+    /**
+     * Mark all configurations from that bundle as changed to reprocess them
+     * @param bundleId The bundle id
+     */
+    public void checkEnvironments(final long bundleId) {
+        for(final String pid : this.getPids()) {
+            final ConfigList configList = this.getConfigurations(pid);
+            for(final Config cfg : configList) {
+                if ( cfg.getBundleId() == bundleId ) {
+                    configList.setHasChanges(true);
+                    break;
+                }
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "State [bundlesLastModified=" + bundlesLastModified + ", environments=" + environments
+                + ", initialHashes=" + initialHashes + "]";
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/model/State.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java (added)
+++ felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,466 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.yaml;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.configurator.impl.logger.SystemLogger;
+import org.apache.felix.configurator.impl.model.BundleState;
+import org.apache.felix.configurator.impl.model.Config;
+import org.apache.felix.configurator.impl.model.ConfigPolicy;
+import org.apache.felix.configurator.impl.model.ConfigurationFile;
+import org.apache.felix.converter.impl.ConverterService;
+import org.osgi.framework.Bundle;
+import org.osgi.service.converter.Converter;
+import org.osgi.service.converter.TypeReference;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.error.YAMLException;
+
+public class Util {
+
+    private static final String INTERNAL_PREFIX = ":configurator:";
+
+    private static final String PROP_VERSION = INTERNAL_PREFIX + "version";
+
+    private static final String PROP_ENVIRONMENTS = "environments";
+
+    private static final String PROP_RANKING = "ranking";
+
+    private static final String PROP_POLICY = "policy";
+
+    public static Converter getConverter() {
+        return new ConverterService(); // TODO use OSGi service
+    }
+
+    public static BundleState readConfigurationsFromBundle(final Bundle bundle, final Set<String> paths) {
+        final BundleState config = new BundleState();
+
+        final List<ConfigurationFile> allFiles = new ArrayList<>();
+        for(final String path : paths) {
+            final List<ConfigurationFile> files = org.apache.felix.configurator.impl.yaml.Util.readYAML(bundle, path);
+            allFiles.addAll(files);
+        }
+        Collections.sort(allFiles);
+
+        config.addFiles(allFiles);
+
+        return config;
+    }
+
+    /**
+     * Read all yaml files from a given path in the bundle
+     * @param bundle The bundle
+     * @param path The path
+     * @return A list of configuration files - sorted by url, might be empty.
+     */
+    public static List<ConfigurationFile> readYAML(final Bundle bundle, final String path) {
+        final List<ConfigurationFile> result = new ArrayList<>();
+        final Enumeration<URL> urls = bundle.findEntries(path, "*.yaml", false);
+        if ( urls != null ) {
+            while ( urls.hasMoreElements() ) {
+                final URL url = urls.nextElement();
+
+                final String filePath = url.getPath();
+                final int pos = filePath.lastIndexOf('/');
+                final String name = path + filePath.substring(pos);
+
+                final String contents = getResource(name, url);
+                if ( contents != null ) {
+                    final ConfigurationFile file = readYAML(name, url, bundle.getBundleId(), contents);
+                    if ( file != null ) {
+                        result.add(file);
+                    }
+                }
+            }
+            Collections.sort(result);
+        } else {
+            SystemLogger.error("No configurations found at path " + path);
+        }
+        return result;
+    }
+
+    /**
+     * Read a single YAML file
+     * @param name The name of the file
+     * @param url The url to that file or {@code null}
+     * @param bundleId The bundle id of the bundle containing the file
+     * @param contents The contents of the file
+     * @return The configuration file or {@code null}.
+     */
+    public static ConfigurationFile readYAML(final String name, final URL url, final long bundleId, final String contents) {
+        final String identifier = (url == null ? name : url.toString());
+        final Map<String, Object> yaml = parseYAML(name, contents);
+        final List<Object> configs = verifyYAML(name, yaml);
+        if ( configs != null ) {
+            final List<Config> configurations = new ArrayList<>();
+            for(final Object obj : configs) {
+                if ( ! (obj instanceof Map) ) {
+                    SystemLogger.error("Ignoring configuration in '" + identifier + "' (not a configuration) : " + obj);
+                } else {
+                    @SuppressWarnings("unchecked")
+                    final Map<String, Object> mainMap = (Map<String, Object>)obj;
+                    if ( mainMap.size() != 1 ) {
+                        SystemLogger.error("Ignoring configuration in '" + identifier + "' (more than one PID) : " + obj);
+                    } else {
+                        final String pid = mainMap.keySet().iterator().next();
+                        final Object configObj = mainMap.values().iterator().next();
+                        if ( ! (configObj instanceof Map) ) {
+                            SystemLogger.error("Ignoring configuration in '" + identifier + "' (no configuration map) : " + obj);
+                        } else {
+                            Set<String> environments = null;
+                            int ranking = 0;
+                            ConfigPolicy policy = ConfigPolicy.DEFAULT;
+
+                            @SuppressWarnings("unchecked")
+                            final Map<String, Object> config = (Map<String, Object>)configObj;
+                            final Dictionary<String, Object> properties = new Hashtable<>();
+                            boolean valid = true;
+                            for(final Map.Entry<String, Object> entry : config.entrySet()) {
+                                String key = entry.getKey();
+                                final boolean internalKey = key.startsWith(INTERNAL_PREFIX);
+                                if ( internalKey ) {
+                                    key = key.substring(INTERNAL_PREFIX.length());
+                                }
+                                final int pos = key.indexOf(':');
+                                String typeInfo = null;
+                                if ( pos != -1 ) {
+                                    typeInfo = key.substring(pos + 1);
+                                    key = key.substring(0, pos);
+                                }
+
+                                final Object value = entry.getValue();
+
+                                if ( internalKey ) {
+                                    // no need to do type conversion based on typeInfo for internal props, type conversion is done directly below
+                                    if ( key.equals(PROP_ENVIRONMENTS) ) {
+                                        environments = Util.getConverter().convert(value).defaultValue(null).to(new TypeReference<Set<String>>() {});
+                                        if ( environments == null ) {
+                                            SystemLogger.warning("Invalid environments for configuration in '" + identifier + "' : " + pid + " - " + value);
+                                        }
+                                    } else if ( key.equals(PROP_RANKING) ) {
+                                        final Integer intObj = Util.getConverter().convert(value).defaultValue(null).to(Integer.class);
+                                        if ( intObj == null ) {
+                                            SystemLogger.warning("Invalid ranking for configuration in '" + identifier + "' : " + pid + " - " + value);
+                                        } else {
+                                            ranking = intObj.intValue();
+                                        }
+                                    } else if ( key.equals(PROP_POLICY) ) {
+                                        final String stringVal = Util.getConverter().convert(value).defaultValue(null).to(String.class);
+                                        if ( stringVal == null ) {
+                                            SystemLogger.error("Invalid policy for configuration in '" + identifier + "' : " + pid + " - " + value);
+                                        } else {
+                                            if ( value.equals("default") || value.equals("force") ) {
+                                                policy = ConfigPolicy.valueOf(stringVal.toUpperCase());
+                                            } else {
+                                                SystemLogger.error("Invalid policy for configuration in '" + identifier + "' : " + pid + " - " + value);
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    try {
+                                        properties.put(key, convert(value, typeInfo));
+                                    } catch ( final IOException io ) {
+                                        SystemLogger.error("Invalid type for configuration in '" + identifier + "' : " + pid + " - " + entry.getKey());
+                                        valid = false;
+                                        break;
+                                    }
+                                }
+                            }
+
+                            if ( valid ) {
+                                final Config c = new Config(pid, environments, properties, bundleId, ranking, policy);
+                                configurations.add(c);
+                            }
+                        }
+                    }
+                }
+            }
+            final ConfigurationFile file = new ConfigurationFile(url, configurations);
+
+            return file;
+        }
+        return null;
+    }
+
+    public static Object convert(final Object value, final String typeInfo) throws IOException {
+        // TODO - binary
+        final String yaml = createYAML(value);
+        if ( typeInfo == null ) {
+            if ( value instanceof String || value instanceof Boolean ) {
+                return value;
+            } else if ( value instanceof Long || value instanceof Double ) {
+                return value;
+            } else if ( value instanceof Integer ) {
+                return ((Integer)value).longValue();
+            } else if ( value instanceof Float ) {
+                return ((Float)value).doubleValue();
+            }
+            if ( value instanceof List ) {
+                @SuppressWarnings("unchecked")
+                final List<Object> list = (List<Object>)value;
+                if ( list.isEmpty() ) {
+                    return new String[0];
+                }
+                final Object firstObject = list.get(0);
+                if ( firstObject instanceof String ) {
+                    return getConverter().convert(list).defaultValue(yaml).to(String[].class);
+                } else if ( firstObject instanceof Boolean ) {
+                    return getConverter().convert(list).defaultValue(yaml).to(Boolean[].class);
+                } else if ( firstObject instanceof Long || firstObject instanceof Integer ) {
+                    return getConverter().convert(list).defaultValue(yaml).to(Long[].class);
+                } else if ( firstObject instanceof Double || firstObject instanceof Float ) {
+                    return getConverter().convert(list).defaultValue(yaml).to(Double[].class);
+                }
+            }
+            return yaml;
+        }
+
+        // scalar types and primitive types
+        if ( "String".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(String.class);
+
+        } else if ( "Integer".equals(typeInfo) || "int".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Integer.class);
+
+        } else if ( "Long".equals(typeInfo) || "long".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Long.class);
+
+        } else if ( "Float".equals(typeInfo) || "float".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Float.class);
+
+        } else if ( "Double".equals(typeInfo) || "double".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Double.class);
+
+        } else if ( "Byte".equals(typeInfo) || "byte".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Byte.class);
+
+        } else if ( "Short".equals(typeInfo) || "short".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Short.class);
+
+        } else if ( "Character".equals(typeInfo) || "char".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Character.class);
+
+        } else if ( "Boolean".equals(typeInfo) || "boolean".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Boolean.class);
+
+        }
+
+        // array of scalar types and primitive types
+        if ( "String[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(String[].class);
+
+        } else if ( "Integer[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Integer[].class);
+
+        } else if ( "int[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(int[].class);
+
+        } else if ( "Long[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Long[].class);
+
+        } else if ( "long[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(long[].class);
+
+        } else if ( "Float[]".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Float[].class);
+
+        } else if ( "float[]".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(float[].class);
+
+        } else if ( "Double[]".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Double[].class);
+
+        } else if ( "double[]".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(double[].class);
+
+        } else if ( "Byte[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Byte[].class);
+
+        } else if ( "byte[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(byte[].class);
+
+        } else if ( "Short[]".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Short[].class);
+
+        } else if ( "short[]".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(short[].class);
+
+        } else if ( "Character[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Character[].class);
+
+        } else if ( "char[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(char[].class);
+
+        } else if ( "Boolean[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(Boolean[].class);
+
+        } else if ( "boolean[]".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(boolean[].class);
+        }
+
+        // Collections of scalar types
+        if ( "Collection<String>".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<String>>() {});
+
+        } else if ( "Collection<Integer>".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Integer>>() {});
+
+        } else if ( "Collection<Long>".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Long>>() {});
+
+        } else if ( "Collection<Float>".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Float>>() {});
+
+        } else if ( "Collection<Double>".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Double>>() {});
+
+        } else if ( "Collection<Byte>".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Byte>>() {});
+
+        } else if ( "Collection<Short>".equals(typeInfo)  ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Short>>() {});
+
+        } else if ( "Collection<Character>".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Character>>() {});
+
+        } else if ( "Collection<Boolean>".equals(typeInfo) ) {
+            return getConverter().convert(value).defaultValue(yaml).to(new TypeReference<List<Boolean>>() {});
+        }
+
+        // unknown type - ignore configuration
+        throw new IOException("Invalid type information: " + typeInfo);
+    }
+
+    /**
+     * Parse a YAML content
+     * @param name The name of the file
+     * @param contents The contents
+     * @return The parsed YAML map or {@code null} on failure,
+     */
+    @SuppressWarnings("unchecked")
+    public static Map<String, Object> parseYAML(final String name, final String contents) {
+        try {
+            final Yaml yaml = new Yaml();
+            try (final StringReader reader = new StringReader(contents) ) {
+                final Object obj = yaml.load(reader);
+                if ( obj instanceof Map ) {
+                    return (Map<String, Object>)obj;
+                }
+                SystemLogger.error("Invalid YAML from " + name);
+            }
+        } catch ( final YAMLException ignore ) {
+            SystemLogger.error("Unable to read YAML from " + name, ignore);
+        }
+        return null;
+    }
+
+    private static String createYAML(final Object data) throws IOException {
+        final DumperOptions options = new DumperOptions();
+        options.setIndent(2);
+        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+        try {
+            final Yaml yaml = new Yaml(options);
+            return yaml.dump(data);
+        } catch ( final YAMLException ye) {
+            throw new IOException(ye);
+        }
+    }
+
+    /**
+     * Verify the YAML according to the rules
+     * @param name The YAML name
+     * @param root The YAML root object.
+     * @return List of objects if valid
+     */
+    @SuppressWarnings("unchecked")
+    public static List<Object> verifyYAML(final String name, final Map<String, Object> root) {
+        if ( root == null ) {
+            return null;
+        }
+        final Object version = root.get(PROP_VERSION);
+        if ( version != null ) {
+
+            final int v = getConverter().convert(version).defaultValue(-1).to(Integer.class);
+            if ( v == -1 ) {
+                SystemLogger.error("Invalid version information in " + name + " : " + version);
+                return null;
+            }
+            // we only support version 1
+            if ( v != 1 ) {
+                SystemLogger.error("Invalid version number in " + name + " : " + version);
+                return null;
+            }
+        }
+        final Object configs = root.get("configurations");
+        if ( configs == null ) {
+            // short cut, we just return false as we don't have to process this file
+            return null;
+        }
+        if ( !(configs instanceof List) ) {
+            SystemLogger.error("Configurations must be a list of configurations in " + name);
+            return null;
+        }
+        return (List<Object>) configs;
+    }
+
+    /**
+     * Read the contents of a resource, encoded as UTF-8
+     * @param name The resource name
+     * @param url The resource URL
+     * @return The contents or {@code null}
+     */
+    public static String getResource(final String name, final URL url) {
+        URLConnection connection = null;
+        try {
+            connection = url.openConnection();
+
+            try(final BufferedReader in = new BufferedReader(
+                    new InputStreamReader(
+                        connection.getInputStream(), "UTF-8"))) {
+
+                final StringBuilder sb = new StringBuilder();
+                String line;
+
+                while ((line = in.readLine()) != null) {
+                    sb.append(line);
+                    sb.append('\n');
+                }
+
+                return sb.toString();
+            }
+        } catch ( final IOException ioe ) {
+            SystemLogger.error("Unable to read " + name, ioe);
+        }
+        return null;
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/main/java/org/apache/felix/configurator/impl/yaml/Util.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java (added)
+++ felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl;
+
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Requirement;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class ConfiguratorTest {
+
+    private Configurator configurator;
+
+    private BundleContext bundleContext;
+
+    private ConfigurationAdmin configurationAdmin;
+
+    @Before public void setup() {
+        bundleContext = mock(BundleContext.class);
+        when(bundleContext.getBundles()).thenReturn(new Bundle[0]);
+        configurationAdmin = mock(ConfigurationAdmin.class);
+
+        configurator = new Configurator(bundleContext, configurationAdmin);
+    }
+
+    private Bundle setupBundle(final long id) {
+        final Bundle b = mock(Bundle.class);
+        when(b.getBundleId()).thenReturn(id);
+        when(b.getLastModified()).thenReturn(5L);
+        final BundleRevision rev = mock(BundleRevision.class);
+        when(b.adapt(BundleRevision.class)).thenReturn(rev);
+        final Requirement req = mock(Requirement.class);
+        when(rev.getRequirements(Util.NS_OSGI_IMPL)).thenReturn(Collections.singletonList(req));
+        final Vector<URL> urls = new Vector<>();
+        urls.add(this.getClass().getResource("/bundles/" + id + ".yaml"));
+        when(b.findEntries("OSGI-INF/configurator", "*.yaml", false)).thenReturn(urls.elements());
+
+        return b;
+    }
+
+    @Test public void testSimpleAddRemove() throws Exception {
+        final Bundle b = setupBundle(1);
+
+        Configuration c1 = mock(Configuration.class);
+        Configuration c2 = mock(Configuration.class);
+        when(configurationAdmin.getConfiguration("a", "?")).thenReturn(c1);
+        when(configurationAdmin.getConfiguration("b", "?")).thenReturn(c2);
+
+        when(c1.getChangeCount()).thenReturn(1L);
+        when(c2.getChangeCount()).thenReturn(1L);
+        configurator.processAddBundle(b);
+
+        configurator.process();
+
+        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=a)")).thenReturn(new Configuration[] {c1});
+        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=b)")).thenReturn(new Configuration[] {c2});
+
+        final Dictionary<String, Object> props1 = new Hashtable<>();
+        props1.put("foo", "bar");
+        verify(c1).update(props1);
+        final Dictionary<String, Object> props2 = new Hashtable<>();
+        props2.put("x", "y");
+        verify(c2).update(props2);
+
+        configurator.processRemoveBundle(1);
+        configurator.process();
+
+        verify(c1).delete();
+        verify(c2).delete();
+    }
+
+    @Test public void testSimpleRankingRemove() throws Exception {
+        final Bundle b1 = setupBundle(1);
+        final Bundle b2 = setupBundle(2);
+
+        Configuration c1 = mock(Configuration.class);
+        Configuration c2 = mock(Configuration.class);
+        when(configurationAdmin.getConfiguration("a", "?")).thenReturn(c1);
+        when(configurationAdmin.getConfiguration("b", "?")).thenReturn(c2);
+
+        when(c1.getChangeCount()).thenReturn(1L);
+        when(c2.getChangeCount()).thenReturn(1L);
+        configurator.processAddBundle(b2);
+        configurator.process();
+
+        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=a)")).thenReturn(new Configuration[] {c1});
+        when(configurationAdmin.listConfigurations("(" + Constants.SERVICE_PID + "=b)")).thenReturn(new Configuration[] {c2});
+
+        final Dictionary<String, Object> props1 = new Hashtable<>();
+        props1.put("foo", "bar2");
+        final Dictionary<String, Object> props2 = new Hashtable<>();
+        props2.put("x", "y2");
+
+        configurator.processAddBundle(b1);
+        configurator.process();
+
+        final Dictionary<String, Object> props3 = new Hashtable<>();
+        props3.put("foo", "bar");
+        final Dictionary<String, Object> props4 = new Hashtable<>();
+        props4.put("x", "y");
+
+        configurator.processRemoveBundle(1);
+        configurator.process();
+
+        configurator.processRemoveBundle(2);
+        configurator.process();
+
+        InOrder inorder = inOrder(c1, c2);
+        inorder.verify(c1).update(props1);
+        inorder.verify(c2).update(props2);
+        inorder.verify(c1).update(props3);
+        inorder.verify(c2).update(props4);
+        inorder.verify(c1).update(props1);
+        inorder.verify(c2).update(props2);
+        inorder.verify(c1).delete();
+        inorder.verify(c2).delete();
+        inorder.verifyNoMoreInteractions();
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/ConfiguratorTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java (added)
+++ felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+
+import org.junit.Test;
+
+public class BundleStateTest {
+
+    @Test public void testReadWrite() throws Exception {
+        final BundleState state = new BundleState();
+
+        final Config c1 = new Config("a", Collections.emptySet(), null, 1,  0, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("b", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+
+        state.add(c1);
+        state.add(c2);
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try ( final ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(state);
+        }
+
+        try ( final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+            final BundleState s = (BundleState) ois.readObject();
+
+            assertEquals(1, s.getConfigurations("a").size());
+            assertEquals(1, s.getConfigurations("b").size());
+        }
+    }
+
+    @Test public void testDifferentPids() {
+        final BundleState state = new BundleState();
+        final Config c1 = new Config("a", Collections.emptySet(), null, 1,  0, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("b", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+
+        state.add(c1);
+        state.add(c2);
+
+        assertEquals(1, state.getConfigurations("a").size());
+        assertEquals(1, state.getConfigurations("b").size());
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/BundleStateTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java (added)
+++ felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.junit.Test;
+
+public class ConfigListTest {
+
+    @Test public void testReadWrite() throws Exception {
+        final ConfigList list = new ConfigList();
+
+        final Config c1 = new Config("a", Collections.singleton("e1"),
+                null, 10, 0, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("a", Collections.singleton("e1"),
+                null, 10, 50, ConfigPolicy.DEFAULT);
+        list.add(c1);
+        list.add(c2);
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try ( final ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(list);
+        }
+
+        try ( final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+            final ConfigList l = (ConfigList) ois.readObject();
+
+            assertEquals(2, l.size());
+        }
+    }
+
+    @Test public void testRanking() {
+        final ConfigList list = new ConfigList();
+        final Config c1 = new Config("a", Collections.emptySet(), null, 1,  0, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("a", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+        final Config c3 = new Config("a", Collections.emptySet(), null, 1,  0, ConfigPolicy.DEFAULT);
+        final Config c4 = new Config("a", Collections.emptySet(), null, 1, 50, ConfigPolicy.DEFAULT);
+        final Config c5 = new Config("a", Collections.emptySet(), null, 1, 20, ConfigPolicy.DEFAULT);
+        final Config c6 = new Config("a", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+
+        list.add(c1);
+        list.add(c2);
+        list.add(c3);
+        list.add(c4);
+        list.add(c5);
+        list.add(c6);
+
+        assertEquals(6, list.size());
+        final Iterator<Config> iter = list.iterator();
+        assertEquals(c4, iter.next());
+        assertEquals(c5, iter.next());
+        assertEquals(c2, iter.next());
+        assertEquals(c6, iter.next());
+        assertEquals(c1, iter.next());
+        assertEquals(c3, iter.next());
+    }
+
+    @Test public void testDifferentBundleIds() {
+        final ConfigList list = new ConfigList();
+        final Config c1 = new Config("a", Collections.emptySet(), null, 2, 10, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("a", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+
+        list.add(c1);
+        list.add(c2);
+
+        assertEquals(2, list.size());
+        final Iterator<Config> iter = list.iterator();
+        assertEquals(c2, iter.next());
+        assertEquals(c1, iter.next());
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigListTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java (added)
+++ felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+
+import org.junit.Test;
+
+public class ConfigTest {
+
+    @Test public void testActiveNoEnv() {
+        final Config c1 = new Config("a", null, null, 1, 0, ConfigPolicy.DEFAULT);
+
+        assertTrue(c1.isActive(Collections.emptySet()));
+        assertTrue(c1.isActive(Collections.singleton("foo")));
+        assertTrue(c1.isActive(new HashSet<>(Arrays.asList("foo", "bar"))));
+    }
+
+    @Test public void testActiveSingleEnv() {
+        final Config c1 = new Config("a", Collections.singleton("foo"), null, 1, 0, ConfigPolicy.DEFAULT);
+
+        assertFalse(c1.isActive(Collections.emptySet()));
+        assertTrue(c1.isActive(Collections.singleton("foo")));
+        assertTrue(c1.isActive(new HashSet<>(Arrays.asList("foo", "bar"))));
+        assertFalse(c1.isActive(Collections.singleton("bar")));
+        assertFalse(c1.isActive(new HashSet<>(Arrays.asList("you", "bar"))));
+    }
+
+    @Test public void testActiveTwoEnv() {
+        final Config c1 = new Config("a", new HashSet<>(Arrays.asList("x", "y")), null, 1, 0, ConfigPolicy.DEFAULT);
+
+        assertFalse(c1.isActive(Collections.emptySet()));
+        assertTrue(c1.isActive(Collections.singleton("x")));
+        assertTrue(c1.isActive(Collections.singleton("y")));
+        assertTrue(c1.isActive(new HashSet<>(Arrays.asList("x", "y"))));
+        assertFalse(c1.isActive(new HashSet<>(Arrays.asList("a", "b"))));
+    }
+
+    @Test public void testReadWrite() throws Exception {
+        final Dictionary<String, Object> props = new Hashtable<>();
+        props.put("x", "1");
+        props.put("y", 1L);
+
+        final Config cfg = new Config("a", Collections.singleton("e1"),
+                props, 10, 50, ConfigPolicy.DEFAULT);
+        cfg.setIndex(70);
+        cfg.setState(ConfigState.UNINSTALL);
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try ( final ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(cfg);
+        }
+
+        try ( final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+            final Config c = (Config) ois.readObject();
+
+            assertEquals("a", c.getPid());
+
+            assertEquals(10, c.getBundleId());
+            assertEquals(50, c.getRanking());
+            assertEquals(70, c.getIndex());
+            assertEquals(ConfigState.UNINSTALL, c.getState());
+            assertEquals(ConfigPolicy.DEFAULT, c.getPolicy());
+
+            assertEquals(2, c.getProperties().size());
+            assertEquals("1", c.getProperties().get("x"));
+            assertEquals(1L, c.getProperties().get("y"));
+
+            assertEquals(1, c.getEnvironments().size());
+            assertEquals("e1", c.getEnvironments().iterator().next());
+        }
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/ConfigTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java (added)
+++ felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.model;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+
+import org.junit.Test;
+
+public class StateTest {
+
+    @Test public void testReadWrite() throws Exception {
+        final State state = new State();
+
+        final Config c1 = new Config("a", Collections.emptySet(), null, 1,  0, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("b", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+
+        state.add(c1);
+        state.add(c2);
+
+        state.setLastModified(1, 5);
+        state.setLastModified(2, 15);
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try ( final ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(state);
+        }
+
+        try ( final ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+            final State s = (State) ois.readObject();
+
+            assertEquals(1, s.getConfigurations("a").size());
+            assertEquals(1, s.getConfigurations("b").size());
+
+            assertEquals(5L, (Object)s.getLastModified(1));
+            assertEquals(15L, (Object)s.getLastModified(2));
+        }
+    }
+
+    @Test public void testDifferentPids() {
+        final State state = new State();
+        final Config c1 = new Config("a", Collections.emptySet(), null, 1,  0, ConfigPolicy.DEFAULT);
+        final Config c2 = new Config("b", Collections.emptySet(), null, 1, 10, ConfigPolicy.DEFAULT);
+
+        state.add(c1);
+        state.add(c2);
+
+        assertEquals(1, state.getConfigurations("a").size());
+        assertEquals(1, state.getConfigurations("b").size());
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/model/StateTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java (added)
+++ felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java Tue Jun 28 13:14:20 2016
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.configurator.impl.yaml;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Array;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.felix.configurator.impl.model.ConfigurationFile;
+import org.junit.Test;
+
+public class UtilTest {
+
+    /** Read the  model from that name */
+    public static String readYAML(final String name) throws Exception {
+
+        try ( final Reader reader = new InputStreamReader(UtilTest.class.getResourceAsStream("/" + name), "UTF-8");
+              final Writer writer = new StringWriter()) {
+
+            final char[] buf = new char[2048];
+            int len = 0;
+            while ((len = reader.read(buf)) > 0) {
+                writer.write(buf, 0, len);
+            }
+
+            return writer.toString();
+        }
+    }
+
+    @Test public void testReadYAML() throws Exception {
+        final ConfigurationFile cg = Util.readYAML("a", new URL("http://a"), 1, readYAML("yaml/valid.yaml"));
+        assertNotNull(cg);
+        assertEquals(2, cg.getConfigurations().size());
+    }
+
+    @Test public void testSimpleTypeConversions() throws Exception {
+        final Object obj = Util.parseYAML("a", readYAML("yaml/simple-types.yaml"));
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> config = (Map<String, Object>)obj;
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> properties = (Map<String, Object>)config.get("config");
+
+        assertTrue(Util.convert(properties.get("string"), null) instanceof String);
+        assertTrue(Util.convert(properties.get("boolean"), null) instanceof Boolean);
+        assertTrue(Util.convert(properties.get("number"), null) instanceof Long);
+        assertTrue(Util.convert(properties.get("float"), null) instanceof Double);
+
+        // arrays
+        assertTrue(Util.convert(properties.get("string.array"), null).getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("string.array"), null), 0) instanceof String);
+        assertTrue(Array.get(Util.convert(properties.get("string.array"), null), 1) instanceof String);
+
+        assertTrue(Util.convert(properties.get("boolean.array"), null).getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("boolean.array"), null), 0) instanceof Boolean);
+        assertTrue(Array.get(Util.convert(properties.get("boolean.array"), null), 1) instanceof Boolean);
+
+        assertTrue(Util.convert(properties.get("number.array"), null).getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), null), 0) instanceof Long);
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), null), 1) instanceof Long);
+
+        assertTrue(Util.convert(properties.get("float.array"), null).getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("float.array"), null), 0) instanceof Double);
+        assertTrue(Array.get(Util.convert(properties.get("float.array"), null), 1) instanceof Double);
+    }
+
+    @Test public void testSimpleTypeConversionsWithTypeHint() throws Exception {
+        final Object obj = Util.parseYAML("a", readYAML("yaml/simple-types.yaml"));
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> config = (Map<String, Object>)obj;
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> properties = (Map<String, Object>)config.get("config");
+
+        assertTrue(Util.convert(properties.get("string"), "String") instanceof String);
+        assertTrue(Util.convert(properties.get("boolean"), "Boolean") instanceof Boolean);
+        assertTrue(Util.convert(properties.get("boolean"), "boolean") instanceof Boolean);
+        assertTrue(Util.convert(properties.get("number"), "Integer") instanceof Integer);
+        assertTrue(Util.convert(properties.get("number"), "int") instanceof Integer);
+        assertTrue(Util.convert(properties.get("number"), "Long") instanceof Long);
+        assertTrue(Util.convert(properties.get("number"), "long") instanceof Long);
+        assertTrue(Util.convert(properties.get("float"), "Double") instanceof Double);
+        assertTrue(Util.convert(properties.get("float"), "double") instanceof Double);
+        assertTrue(Util.convert(properties.get("float"), "Float") instanceof Float);
+        assertTrue(Util.convert(properties.get("float"), "float") instanceof Float);
+        assertTrue(Util.convert(properties.get("number"), "Byte") instanceof Byte);
+        assertTrue(Util.convert(properties.get("number"), "byte") instanceof Byte);
+        assertTrue(Util.convert(properties.get("number"), "Short") instanceof Short);
+        assertTrue(Util.convert(properties.get("number"), "short") instanceof Short);
+        assertTrue(Util.convert(properties.get("string"), "Character") instanceof Character);
+        assertTrue(Util.convert(properties.get("string"), "char") instanceof Character);
+
+        // arrays
+        assertTrue(Util.convert(properties.get("string.array"), "String[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("string.array"), "String[]"), 0) instanceof String);
+        assertTrue(Array.get(Util.convert(properties.get("string.array"), "String[]"), 1) instanceof String);
+
+        assertTrue(Util.convert(properties.get("boolean.array"), "Boolean[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("boolean.array"), "Boolean[]"), 0) instanceof Boolean);
+        assertTrue(Array.get(Util.convert(properties.get("boolean.array"), "Boolean[]"), 1) instanceof Boolean);
+
+        // the following would throw class cast exceptions
+        boolean[] a0 = (boolean[])Util.convert(properties.get("boolean.array"), "boolean[]");
+        assertNotNull(a0);
+        int[] a1 = (int[])Util.convert(properties.get("number.array"), "int[]");
+        assertNotNull(a1);
+        long[] a2 = (long[])Util.convert(properties.get("number.array"), "long[]");
+        assertNotNull(a2);
+        double[] a3 = (double[])Util.convert(properties.get("float.array"), "double[]");
+        assertNotNull(a3);
+        float[] a4 = (float[])Util.convert(properties.get("float.array"), "float[]");
+        assertNotNull(a4);
+        byte[] a5 = (byte[])Util.convert(properties.get("number.array"), "byte[]");
+        assertNotNull(a5);
+        short[] a6 = (short[])Util.convert(properties.get("number.array"), "short[]");
+        assertNotNull(a6);
+        char[] a7 = (char[])Util.convert(properties.get("string.array"), "char[]");
+        assertNotNull(a7);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Integer[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Integer[]"), 0) instanceof Integer);
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Integer[]"), 1) instanceof Integer);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Long[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Long[]"), 0) instanceof Long);
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Long[]"), 1) instanceof Long);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Byte[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Byte[]"), 0) instanceof Byte);
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Byte[]"), 1) instanceof Byte);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Short[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Short[]"), 0) instanceof Short);
+        assertTrue(Array.get(Util.convert(properties.get("number.array"), "Short[]"), 1) instanceof Short);
+
+        assertTrue(Util.convert(properties.get("float.array"), "Float[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("float.array"), "Float[]"), 0) instanceof Float);
+        assertTrue(Array.get(Util.convert(properties.get("float.array"), "Float[]"), 1) instanceof Float);
+
+        assertTrue(Util.convert(properties.get("float.array"), "Double[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("float.array"), "Double[]"), 0) instanceof Double);
+        assertTrue(Array.get(Util.convert(properties.get("float.array"), "Double[]"), 1) instanceof Double);
+
+        assertTrue(Util.convert(properties.get("string.array"), "Character[]").getClass().isArray());
+        assertTrue(Array.get(Util.convert(properties.get("string.array"), "Character[]"), 0) instanceof Character);
+        assertTrue(Array.get(Util.convert(properties.get("string.array"), "Character[]"), 1) instanceof Character);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test public void testCollectionTypeConversion() throws Exception {
+        final Object obj = Util.parseYAML("a", readYAML("yaml/simple-types.yaml"));
+        final Map<String, Object> config = (Map<String, Object>)obj;
+        final Map<String, Object> properties = (Map<String, Object>)config.get("config");
+
+        assertTrue(Util.convert(properties.get("string.array"), "Collection<String>") instanceof Collection<?>);
+        assertTrue(((Collection<String>)Util.convert(properties.get("string.array"), "Collection<String>")).iterator().next() instanceof String);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Collection<Integer>") instanceof Collection<?>);
+        assertTrue(((Collection<Integer>)Util.convert(properties.get("number.array"), "Collection<Integer>")).iterator().next() instanceof Integer);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Collection<Long>") instanceof Collection<?>);
+        assertTrue(((Collection<Long>)Util.convert(properties.get("number.array"), "Collection<Long>")).iterator().next() instanceof Long);
+
+        assertTrue(Util.convert(properties.get("float.array"), "Collection<Float>") instanceof Collection<?>);
+        assertTrue(((Collection<Float>)Util.convert(properties.get("float.array"), "Collection<Float>")).iterator().next() instanceof Float);
+
+        assertTrue(Util.convert(properties.get("float.array"), "Collection<Double>") instanceof Collection<?>);
+        assertTrue(((Collection<Double>)Util.convert(properties.get("float.array"), "Collection<Double>")).iterator().next() instanceof Double);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Collection<Short>") instanceof Collection<?>);
+        assertTrue(((Collection<Short>)Util.convert(properties.get("number.array"), "Collection<Short>")).iterator().next() instanceof Short);
+
+        assertTrue(Util.convert(properties.get("number.array"), "Collection<Byte>") instanceof Collection<?>);
+        assertTrue(((Collection<Byte>)Util.convert(properties.get("number.array"), "Collection<Byte>")).iterator().next() instanceof Byte);
+
+        assertTrue(Util.convert(properties.get("string.array"), "Collection<Character>") instanceof Collection<?>);
+        assertTrue(((Collection<Character>)Util.convert(properties.get("string.array"), "Collection<Character>")).iterator().next() instanceof Character);
+
+        assertTrue(Util.convert(properties.get("boolean.array"), "Collection<Boolean>") instanceof Collection<?>);
+        assertTrue(((Collection<Boolean>)Util.convert(properties.get("boolean.array"), "Collection<Boolean>")).iterator().next() instanceof Boolean);
+    }
+}

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/sandbox/cziegeler/configurator/src/test/java/org/apache/felix/configurator/impl/yaml/UtilTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Added: felix/sandbox/cziegeler/configurator/src/test/resources/bundles/1.yaml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/resources/bundles/1.yaml?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/resources/bundles/1.yaml (added)
+++ felix/sandbox/cziegeler/configurator/src/test/resources/bundles/1.yaml Tue Jun 28 13:14:20 2016
@@ -0,0 +1,5 @@
+configurations:
+  - a:
+      foo: bar
+  - b:
+      x: y

Added: felix/sandbox/cziegeler/configurator/src/test/resources/bundles/2.yaml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/resources/bundles/2.yaml?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/resources/bundles/2.yaml (added)
+++ felix/sandbox/cziegeler/configurator/src/test/resources/bundles/2.yaml Tue Jun 28 13:14:20 2016
@@ -0,0 +1,5 @@
+configurations:
+  - a:
+      foo: bar2
+  - b:
+      x: y2

Added: felix/sandbox/cziegeler/configurator/src/test/resources/yaml/simple-types.yaml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/resources/yaml/simple-types.yaml?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/resources/yaml/simple-types.yaml (added)
+++ felix/sandbox/cziegeler/configurator/src/test/resources/yaml/simple-types.yaml Tue Jun 28 13:14:20 2016
@@ -0,0 +1,17 @@
+config:
+  string: bar
+  boolean: true
+  number: 17
+  float: 5.0
+  string.array: 
+    - a
+    - b
+  boolean.array:
+    - true
+    - false
+  number.array:
+    - 3
+    - 4
+  float.array:
+    - 1.0
+    - 2.0

Added: felix/sandbox/cziegeler/configurator/src/test/resources/yaml/valid.yaml
URL: http://svn.apache.org/viewvc/felix/sandbox/cziegeler/configurator/src/test/resources/yaml/valid.yaml?rev=1750501&view=auto
==============================================================================
--- felix/sandbox/cziegeler/configurator/src/test/resources/yaml/valid.yaml (added)
+++ felix/sandbox/cziegeler/configurator/src/test/resources/yaml/valid.yaml Tue Jun 28 13:14:20 2016
@@ -0,0 +1,5 @@
+configurations:
+  - a:
+      foo: bar
+  - b:
+      x: y



Mime
View raw message